From dfdb56daee60ddeb4c67c6bed6a38c6aba6d6a37 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Sun, 30 Aug 2020 16:43:53 -0400 Subject: [PATCH 01/13] Bump up version to 0.7.1 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 0e72f8c6..e56b276c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "LatticeTools" uuid = "8a267902-5e0e-44c3-8ef8-9b2b5c352816" author = "Kyungmin Lee" -version = "0.7.0" +version = "0.7.1" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" From ee61b2a701848a92360309624d49253d3bf07752 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Sun, 30 Aug 2020 21:18:33 -0400 Subject: [PATCH 02/13] Add logo directory --- logo/Kagome.jl | 216 ++++++++++++++++++++++++++++++++++++++++++++++ logo/Project.toml | 3 + logo/lattice.json | 51 +++++++++++ logo/make.jl | 63 ++++++++++++++ 4 files changed, 333 insertions(+) create mode 100644 logo/Kagome.jl create mode 100644 logo/Project.toml create mode 100644 logo/lattice.json create mode 100644 logo/make.jl diff --git a/logo/Kagome.jl b/logo/Kagome.jl new file mode 100644 index 00000000..291d41dc --- /dev/null +++ b/logo/Kagome.jl @@ -0,0 +1,216 @@ +module Kagome + +using LatticeTools + + +NN_BOND_TYPES = [ + ([ 0, 0], "A", [ 0, 0], "B", 1), + ([ 0, 0], "B", [ 0, 0], "C", 1), + ([ 0, 0], "C", [ 0, 0], "A", 1), + + ([ 1, 1], "A", [ 1, 0], "B",-1), + ([ 1, 0], "B", [ 0, 0], "C",-1), + ([ 0, 0], "C", [ 1, 1], "A",-1), +] + + +NNN_BOND_TYPES = [ + ([ 0, 0], "A", [ 1, 0], "B", 1), # ◁ + ([ 1, 0], "B", [ 0,-1], "C", 1), + ([ 0,-1], "C", [ 0, 0], "A", 1), + ([ 0, 0], "C", [ 1, 0], "A",-1), + ([ 1, 0], "A", [ 0,-1], "B",-1), # ▷ + ([ 0,-1], "B", [ 0, 0], "C",-1), +] + + +export make_kagome_lattice +export make_kagome_obc + + +function make_kagome_lattice(size_matrix ::AbstractMatrix{<:Integer}; compute_symmetry::Bool=false) + latticevectors = [1 -0.5; 0 0.5*sqrt(3.0)]; + unitcell = make_unitcell(latticevectors, SiteType=String) + addsite!(unitcell, "A", carte2fract(unitcell, [0.5, 0.0])) + addsite!(unitcell, "B", carte2fract(unitcell, [0.25, 0.25*sqrt(3.0)])) + addsite!(unitcell, "C", carte2fract(unitcell, [0.5+0.25, 0.25*sqrt(3.0)])) + + lattice = make_lattice(unitcell, size_matrix) + hypercube = lattice.hypercube + supercell = lattice.supercell + tsym = TranslationSymmetry(lattice) + psym = little_symmetry(tsym, project(PointSymmetryDatabase.get(25), [1 0 0; 0 1 0])) + tsymbed = embed(lattice, tsym) + psymbed = embed(lattice, psym) + ssymbed = tsymbed ⋊ psymbed + + nnbonds = [] + nnnbonds = [] + + for r in lattice.bravais_coordinates + for (rowvec, rowsite, colvec, colsite, bondsign) in NN_BOND_TYPES + R_row, r_row = hypercube.wrap(r .+ rowvec) + R_col, r_col = hypercube.wrap(r .+ colvec) + rowsite_super = (rowsite, r_row) + colsite_super = (colsite, r_col) + irow = get(supercell.siteindices, rowsite_super, -1) + icol = get(supercell.siteindices, colsite_super, -1) + push!(nnbonds, ((irow, icol), R_col-R_row, bondsign)) + end + for (rowvec, rowsite, colvec, colsite, bondsign) in NNN_BOND_TYPES + R_row, r_row = hypercube.wrap(r .+ rowvec) + R_col, r_col = hypercube.wrap(r .+ colvec) + rowsite_super = (rowsite, r_row) + colsite_super = (colsite, r_col) + irow = get(supercell.siteindices, rowsite_super, -1) + icol = get(supercell.siteindices, colsite_super, -1) + push!(nnnbonds, ((irow, icol), R_col-R_row, bondsign)) + end + end + + nn_triangles = [] + for r in lattice.bravais_coordinates + triangle = [] + for (rowvec, roworb, colvec, colorb, bondsign) in NN_BOND_TYPES[1:3] + R_row, r_row = hypercube.wrap(r .+ rowvec) + R_col, r_col = hypercube.wrap(r .+ colvec) + roworb_super = (roworb, r_row) + colorb_super = (colorb, r_col) + irow = get(supercell.siteindices, roworb_super, -1) + icol = get(supercell.siteindices, colorb_super, -1) + push!(triangle, ((irow, icol), R_col-R_row)) + end + push!(nn_triangles, (triangle, 1)) + + triangle = [] + for (rowvec, roworb, colvec, colorb, bondsign) in NN_BOND_TYPES[4:6] + R_row, r_row = hypercube.wrap(r .+ rowvec) + R_col, r_col = hypercube.wrap(r .+ colvec) + roworb_super = (roworb, r_row) + colorb_super = (colorb, r_col) + irow = get(supercell.siteindices, roworb_super, -1) + icol = get(supercell.siteindices, colorb_super, -1) + push!(triangle, ((irow, icol), R_col-R_row)) + end + push!(nn_triangles, (triangle, -1)) + end + + + nnn_triangles = [] + for r in lattice.bravais_coordinates + triangle = [] + for (rowvec, roworb, colvec, colorb, bondsign) in NNN_BOND_TYPES[1:3] + R_row, r_row = hypercube.wrap(r .+ rowvec) + R_col, r_col = hypercube.wrap(r .+ colvec) + roworb_super = (roworb, r_row) + colorb_super = (colorb, r_col) + irow = get(supercell.siteindices, roworb_super, -1) + icol = get(supercell.siteindices, colorb_super, -1) + push!(triangle, ((irow, icol), R_col-R_row)) + end + push!(nnn_triangles, (triangle, 1)) + + triangle = [] + for (rowvec, roworb, colvec, colorb, bondsign) in NNN_BOND_TYPES[4:6] + R_row, r_row = hypercube.wrap(r .+ rowvec) + R_col, r_col = hypercube.wrap(r .+ colvec) + roworb_super = (roworb, r_row) + colorb_super = (colorb, r_col) + irow = get(supercell.siteindices, roworb_super, -1) + icol = get(supercell.siteindices, colorb_super, -1) + push!(triangle, ((irow, icol), R_col-R_row)) + end + push!(nnn_triangles, (triangle, -1)) + end + + + return (unitcell=unitcell, + lattice=lattice, + space_symmetry_embedding=ssymbed, + nearest_neighbor_bonds=nnbonds, + next_nearest_neighbor_bonds=nnnbonds, + nearest_neighbor_triangles=nn_triangles, + next_nearest_neighbor_triangles=nnn_triangles,) +end + + + + +function make_kagome_obc(sites::AbstractVector{<:Tuple}) + site_set = Set(sites) + + min_R1 = minimum(R[1] for (sitetype, R) in sites) + max_R1 = maximum(R[1] for (sitetype, R) in sites) + min_R2 = minimum(R[2] for (sitetype, R) in sites) + max_R2 = maximum(R[2] for (sitetype, R) in sites) + + n1 = max_R1 - min_R1 + 1 + n2 = max_R2 - min_R2 + 1 + + big_kagome = make_kagome_lattice([n1+1 0; 0 n2+1]) + + site_folding = Dict{Int, Int}() + + new_kagome_supercell = make_unitcell( + big_kagome.lattice.supercell.latticevectors, + SiteType=Tuple{String, Vector{Int}} + ) + + for (siteindex, ((sitetype, siteuc), sitecoord)) in enumerate(big_kagome.lattice.supercell.sites) + if (sitetype, siteuc + [min_R1, min_R2]) in site_set + addsite!(new_kagome_supercell, (sitetype, siteuc + [min_R1, min_R2]), sitecoord) + site_folding[siteindex] = numsite(new_kagome_supercell) + end + end + + + nn_bonds = Tuple{Int, Int}[] + for ((i, j), R, _) in big_kagome.nearest_neighbor_bonds + if !haskey(site_folding, i) || !haskey(site_folding, j) || !iszero(R) + continue + end + ip = site_folding[i] + jp = site_folding[j] + if ip < jp + push!(nn_bonds, (ip, jp)) + else + push!(nn_bonds, (jp, ip)) + end + end + + #@show big_kagome.nearest_neighbor_triangles + + nn_triangles = Tuple{Int, Int, Int}[] + for (tri, sgn) in big_kagome.nearest_neighbor_triangles + triangle_vertices = Set{Int}() + complete_triangle = true + for ((i, j), R) in tri + if !iszero(R) + complete_triangle = false + break + end + ip = get(site_folding, i, -1) + jp = get(site_folding, j, -1) + + if ip <= 0 || jp <= 0 + complete_triangle = false + break + end + + push!(triangle_vertices, ip) + push!(triangle_vertices, jp) + end + + !complete_triangle && continue + + push!(nn_triangles, tuple(sort(collect(triangle_vertices))...)) + end + + return (unitcell=new_kagome_supercell, + nearest_neighbor_bonds=nn_bonds, + nearest_neighbor_triangles=nn_triangles) + +end + + +end # module Kagome diff --git a/logo/Project.toml b/logo/Project.toml new file mode 100644 index 00000000..fc7a8820 --- /dev/null +++ b/logo/Project.toml @@ -0,0 +1,3 @@ +[deps] +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +Luxor = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc" diff --git a/logo/lattice.json b/logo/lattice.json new file mode 100644 index 00000000..832f01aa --- /dev/null +++ b/logo/lattice.json @@ -0,0 +1,51 @@ +{ + "sites": [ + ["A", [0, 0]], + ["B", [0, 0]], + ["C", [0, 0]], + + ["A", [1, 0]], + ["B", [1, 0]], + ["C", [1, 0]], + + ["A", [2, 0]], + ["B", [2, 0]], + ["C", [2, 0]], + + ["B", [3, 0]], + + ["A", [0, 1]], + ["B", [0, 1]], + ["C", [0, 1]], + + ["A", [1, 1]], + ["B", [1, 1]], + ["C", [1, 1]], + + ["A", [2, 1]], + ["B", [2, 1]], + ["C", [2, 1]], + + ["A", [3, 1]], + ["B", [3, 1]], + ["C", [3, 1]], + + ["A", [1, 2]], + ["B", [1, 2]], + ["C", [1, 2]], + + ["A", [2, 2]], + ["B", [2, 2]], + ["C", [2, 2]], + + ["A", [3, 2]], + ["B", [3, 2]], + ["C", [3, 2]], + + ["A", [2, 3]], + + ["A", [3, 3]], + ["C", [-1, 0]] + ] + +} \ No newline at end of file diff --git a/logo/make.jl b/logo/make.jl new file mode 100644 index 00000000..dae4101a --- /dev/null +++ b/logo/make.jl @@ -0,0 +1,63 @@ +using Luxor +using JSON +using LatticeTools + +include("Kagome.jl") + +lattice_data = JSON.parsefile("lattice.json") +sites = [(sitetype, [R...]) for (sitetype, R) in lattice_data["sites"]] +kagome = Kagome.make_kagome_obc(sites) +site_coordinates = [] +site_types = String[] +for ((sitetype, sitesubscript), sitefc) in kagome.unitcell.sites + sitecc = fract2carte(kagome.unitcell, sitefc) + push!(site_coordinates, sitecc) + push!(site_types, sitetype) +end +site_coordinates = hcat(site_coordinates...) +site_coordinates[2,:] = -site_coordinates[2,:] + +Drawing(840, 300, "logo.png") + +origin() +translate(-460, 110) + +let ratio = 88, radius = 10, radius_large = 14, offset = (0,0) + sethue("gray") + setline(2) + for (i, j) in kagome.nearest_neighbor_bonds + ri = site_coordinates[:,i] + rj = site_coordinates[:,j] + line( + Point(ri[1]*ratio + offset[1], ri[2]*ratio + offset[2]), + Point(rj[1]*ratio + offset[1], rj[2]*ratio + offset[2]), + :stroke + ) + end + + #sethue("white") + #for sc in values(site_coordinates), r in eachcol(sc) + # circle(Point(r[1]*ratio + offset[1], r[2]*ratio + offset[2]), radius_large, :fill) + #end + sitecolor = Dict("A" => "brown3", "B" => "forestgreen", "C" => "mediumorchid3") + for (sitetype, r) in zip(site_types, eachcol(site_coordinates)) + sethue("white") + circle(Point(r[1]*ratio + offset[1], r[2]*ratio + offset[2]), radius_large, :fill) + sethue(sitecolor[sitetype]) + circle(Point(r[1]*ratio + offset[1], r[2]*ratio + offset[2]), radius, :fill) + end +end + +translate(400, -136) +sethue("black") +fontsize(144) +fontface("Tamil MN") +texttrack("Lattice", Point(0, 0), -50, 144) +translate(0, 140) +texttrack("Tools.jl", Point(0, 0), -50, 144) + +setcolor(sethue("royalblue")..., 1.0) +ellipse(286.3, -239.6, 25, 22.6, :fill) + +finish() +#preview() From 2ddb34d6d373db7edd2d382ce630c1e60224f595 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Sun, 30 Aug 2020 21:18:40 -0400 Subject: [PATCH 03/13] Update logo --- docs/src/assets/logo.png | Bin 22492 -> 22716 bytes docs/src/assets/logo.svg | 120 --------------------------------------- logo/make.jl | 2 +- 3 files changed, 1 insertion(+), 121 deletions(-) delete mode 100644 docs/src/assets/logo.svg diff --git a/docs/src/assets/logo.png b/docs/src/assets/logo.png index 3373fbfab88b05fe2f0ffe9bb20e3685058c67e3..352d1351b82e1d7dcff7cfcee2cc393ec1db211f 100644 GIT binary patch literal 22716 zcmcG$g%hM-^ra=lfScPt$+el`06-1A6%$qd9KSW=978lxE4+v7#%zXN(5EcIziV)s!AQ$Z z!WzY7Wq!Ps;p9=3v?LIvVZA5QbB~Ebf!*x+^xFGk#?HW&z(*vDDB9(xb`S%6jw0NP zhHiEZPft%}9%ZC`pS@~=k~H$dInkrU+(piFb9-kYK3^#lfc^jQdj1Ao3&00oX9Y+& zNA!`vsU6`3F5kjw(f7vYzf2gvveKUFTgbZd^Q$|x@T*@>Se-J~^P8__m9t2ZIh^V8BL99awcavo9l>T|Z-_OsFVV79;v8&Ox z7L@8xOFj>jA}-*&t1`>=@e?*PrXLLUyf0H|VYX=S7r+lRcIGZkfr${{;}*TptrHU?Dp?%-KKDK-=~u1Rdu5ls#Kn`i z5*`^Mlr1-62K;rLc|Abqczjq1sLP8m+tYr3eK!atlBUhw{5aHj#xl(&G-y@$52e>< zBL4%~xBciLH(~|=oCJvPUpKa}7(ZN%Gf}T2x0otN1*D+3VyzW6Yjy{n@6yw=>un)$ z67glt^kKQ7QVGZ*9V{iJLRWIdyNy&er^5K7%@jIt{b}p1A4&s6@e6(^0e}@U=)7z4 zsU^ynvT0O;N?hXO$H_UCoe?ar`ZHPV+C@wvw#>|{qs+~(!gQT=dvPo==GUPx`z(-tRr*OG8vIcW%f6K=L-2bT5}7zlH-3b* zA{=@0NY^bR1O+3;0~c0r16TfFiC%a^8y$s1wl{#oLp?hA)9&@3sE2O$%{V4A6$6!( zXfN{+OsN5&Tn<(;{pgP#{B<|8n7z)&lP{j|MNl6QLnYB)iTS_`#Y>OtFX<-9rrCl< z>s)z8`x4@+z)_E*cJ|MHfNu;fKK(O%vfQ|Niozl`({VF7Lf!c2{@ubaRNM<1t2S-L z-11nb>kHgbuX!ZMnwtba@XAKvC(B* zJ$I4rrLVOpFfG*k)0Wq*H{{81b1qc%6(n^esPnB{_c}C z8wF$TM{Nmgel7M~XL<@6?Q~J;C0vq3^yJjUK`w}dFpu-|@pM#Zh9y%Aok%PjzQWjn z&6n7Yt)cdtD&*mm$a(wp2Z?}8$B6mbAbq}@v$>#Ap7&pG_d64LT)dMDdCG3n*b0qA zhUH|;j*WBB?Q*fCJ*#yl$aZ(xjeR@zN&BirJTFkgvGVjd2B1)6 zz6X``{up~GH}|5qe{@eY=|XcOV`Y*w7vc8bxtiI7?|#{LJV0dB z0*T0B6HX4$*p6V%Y3XFn#qu|oBOS*;1t~=+YUVicy>w+lxDH=AP7>#R;-$7q%i_fj z8jj1HTt%KfB`MoO=1x z%7=ER?QE7`EKcU^qESHE|1)v_-B>8oGK~NJvN*|^YTmB4;JuM?f zu6qqQO@9%xs`WmfyP!0t8R~cW=J}e5Sy=6E4UK@#XHiF1ZD!XwX9@nFKc5R}iY*J{FAQ|> zu1Z7HQ7%kUv!@7d9KB)rm@ad!dXHk3mxS^0L&N=Kw${K`j`3{d2j-_zbu^yC8)9(qtMFin$A{pGWnqElk@fTE&jOTF6nKK6p<$_1_E?1C7(@CS zR9>_bf(#why^+(KU}dSmAd%J5gM$OJ@h-U}bG6Y{(QSzj;QBMM`!kxHm0UX9J;4{$ zG!z3hl~})S2#`Mf!*nRa!s%L*u~eJ!I7e}VBYn8(^v23scr_!=a`JvMy$3Qn%8*X0 zFf-(CruQB7;9M2*{O`Xa-YHNn@kydfG9JIce~hYI=~r=$%40cQp~I$A=LUl>0WuKl z>U`2v(8(%j(!n`^Hk3!u`SH_}oghhOhs&Fb{TtSAGkQ9y#V>I-02%D6dp)3y)a0O9 zL*UY(m)8kIGJI;%ZWwHD9FyvY`?NoZIMG-3Y`Ftn5J7Ljj%S&K?TqI}eThOPd3hGZ z@H(K*L~T^0ro>onv=T^!7LqiCMj2WRzcVu6(7_xhh)KXLA!=C1mfvMFVpsAWhBXGrgLv8KGJ_5 zAb|<_;#`2RVWYp3V_FN7@l7H|D!?ZM6o;xMQ@pPsuL}KX$ZK zSaO>y@TnZ*JKl{5LT0mpTb4S?Fad488c+`i2yoEWK^Oxkkcy_F-%4C%WQ^c_b!quO zq7*0m`NSt+A)Q>%ygDsEM8PO>MQ~OwZ^@_gamWj6MiE*rIxIv2&cA*s01fk~-)&!N z(CrLnvlmuq~b@sYjJ^&z60?YKMLDoxTF2wu3nXw5i8kZJ){4 z3fCVocsq#H@`84bvP`c0?W#8Ztv*!~XN9c&bu<4vDeNCj2QE+R`tNVQ^arg@Pi@o* zh==H6!KduY=ZcN{CID^-ZyvatrmCj!1XiUZ#&WFZO%#-AF{FNN!$YhTg9*G1-z~Hm zd~>BDKus_Fy{GDLjq^jXM_dvb32qCZtBA>Z{xXt`rOT}UikxTKx|uS4xCfwy+3i#; z1!-3$(fp2KQ<$}NWKCfjfc$FWqFC4>N5D8b0{%u5`5$(D6%=9Qh{3)vrz#VryNzX9 zWq~)4QxdqZtdPH-AlkeG0OjH4-VlU7-2x}N_LoAy$d(#K3B*+?nq1M+1acQ{20~j% z1QZ_2(0|i=S4q`p=tmgp1-LzIUMa2M~{9gnmN5IO%J!IEjH@mPphrHLIs2% z@uq5{&*(RE^74dO9tN;L`cdXhx{5|u6slCM`SbejOwGxuigc>u#)g(P-iHD>K z1y&Ar>*l(&!(9nOoEZ(nJxOFvXr4g?znS3vP?Y^5BJG9fGA_$SzKErV(ZLSf@txm@ zsnZrmoqo(G3T#9X{|Ku`<9F7!(9N-kq`q}35 z8ZD~alXw#Uv~cq;bF`HhAws}=fs0cM%j(=xiz1!<%&9R#3boWoJxt(FjdMsrD6Yqr zR}xR6$YV78vm8ISe(|R);lwao1?7#IDu-ObgAN*&D8s;m+)=e+BZ|wl)L?F_sj?pN zn(lG|?+B}R$8R1%C1=+t$tx3-tWxaOGL{-4iuRUgoG%B@>be{tz>FuVqE$vl@H#m; z-E--@Qi6o&YaaI{>P|L&&j6u5*}muE34Rep+M``Ahncg24UjNb`a1XHrX%W3v~bj% zWV!iXU-$2Wz+2;4%R{c%X#X+IvAKLrjPUHP*0>tt&5LYwLw_5|C>MX z@YUQI*Zcm%a&uw$TRuS#*~@*W22GXw@~DrzdJ&eS@7Yml@fCm_2`S?|q0u0TS$DL0 z_oebv1LRXvPh^M}Zlh=7K~lxmY1cc&2%-rDM35Oa_fE?6ik?oXcJRq5vUsZSWZ#9; z!u0J$HSy~%j`OA`j~uS4vli11pSl-BpZ&~>J|i&Y71P8a4p z{6?mV$S#8@I3Lzmp7QXP%>Bw1sd~%kP@O1cvA$t3J^ZzN)y+>RX{#$IP&n0Pafs)~ zn*zO+Y>|U>?bTeoL)nztS;40FThjwV^CyD~l7t}Ah z$TBbGC48pFzs?Iwp?Q(8D>|g3d4A55Or7sV3xlG@tWKAG>Uyqu;459UqlwaxW0AX8 zI_HVgwHcjxZIa~~|Ce^L78bX$7Ald>|xm^Xog(o;v(h#yL>jm#DxTv$4j zMCW+<^-9)Je6e@5Eib0R8s@k?6>0an`eeH)%{#oX*0kErP97LZ%oU{0o{iG7_DO>898cT6-8r&rX_3~Ut?3oVJCopz@$&>he{3IP?ivI5#iX)1ds#i(^ zK%vw}jrGrGw))SH3|5Z?JC)6KsTyB&mYWN%T!DZH22e3wxqU)n)xIher&V70M~`N; zhV!YzAyO=@e)G-J;7Il2FP!o6+8&3vo+1iXDGUL7v6k2Dfif&^=*YU z;o&K{nCBUPWWV%1-FM~eUD;h%e`mzlt?4%sd`Rl9b}q0Bl?3Xr+x3ae%L*Eoo>3yF z*P0Bm_7{Ti65^zO8FMBo@6H}y6z;E3B$CbSE#hv?gmBh&O4fEeiL3@lE=wz~$!JA; zX9@5JV-WrQN>lYPB6j5JwdMz4z!seyC^fuUegTPQzgCGUrPN%oc*m*E#bNxtcq6TS?3jH$)3%-DG+@f{&;Foo9$4x$*nnw zE!02!kE{;KH-^7Vznr{z2`OxclJs~yoifZ_cFulIcGCWlse0QM3?puG2zkT1`+Kfd zTcerG@o5stz~rP$grQowvuSZ@slz8VwTbJC9u19J&gisk;Yt?5m*YLv-uH zvbO9HA@r-8@i*(5_h9wwH9O;qF=sWg*VqVtxHI8sQ2{|gL1f^qF6eink69Y)D0Wlmi z@H}-=`l4v)=!j{>Yb61(Gf8C8Ieni~Ec6OB?X2T!Ep&&`--CSN&0^lZGqPc8fGya@>K%o@Uy5L-IaJuL0dBNV2zHkivQ*2Pq5lJHMnnC z_n4lEmcLI3wuVD553;#EG%cj~Y zsE~DAU+}B?Kea`cnKz-ecmD!ERrEBd(O&IxOPFekXH)P~hI~MAeRsq;o}G57yCFy_ z5*3CUwllJM@IF&65O=mOG3Wt)EZ#g5qAaFmZy74TSZ;Owu&az&`ogsxTL?on!Irqr zZ8-WDzr;z1;)YcH1~G)Ywg}ans-S(RRMymUH+g{gk^8{AAH21mRjT7-F0lm@;G?F0 zKq;Q%W%U;F{&tj&!cNiXt|W+Yo`L$lk#anC-qGKn;6N`)=31*GgNpC5k&6D%*(^>f z|DJT%r$^3IM3X=^`N{ieHW}n$AP(7|-yV;-xjvx)*t-Jc?bv)6H0O@|H&67Qz^$0l z)n5oT7}VaLCaxBQCl1MaM@K$&yQj0rfZx)A!Fm~UH*FjdS7eAE8 zb~`&yr(T=VZLd+KtH|v_chiqouyt zy)(!OkHz!ySH2Y#H-rgC*hv_aboGrI!?=|}q+$Rh9&_HjFcacXYGD2Pl0&EV=K8|3 z+;XN$5h#x<7#tlK*bfL6KF`{^zS#AA#5amHUo4eP;?D5m{vj8LVR}y*j8lY;+-v9L zPf7maZ!#s?g>Vn}7M6^4FHBJi5X6}0_|q4CN(5g3aQ#J=2>~)lO=^T01k8Z0@fySd z*6i$TzWS=FbG2};(c$5E8ki1hA80lJ3{W>EKos@UkXzav-**`l>LB#Xj z)5wlpyYdo-EOAnMaCoJfm=WXy#=KILVQJjwM0Bi&L|`6&sRIN-t&73a>*wdhLOpPr zxtca{(o5C*^H0Q(lK3R1YwE&VN+AK9G3t%DKt@9ygSqhY*eSF<*w_ryIHRNX(eB(0 zN#Tts-y24U_fEl1=4S^h;kr(&A}H3G*@*jOx9dzd2($4B?KHKQ)^jq7A~j3uD6zq} z5J=k3(tgPM(sp4Zx4=?CYUUmQd%iiUVMUR3!Dm^$U3LwaEjkqxGn*&vAnrZ8o9G~o z;H2}|1N(;@w0@nANsRmw{Rb*-bWU#W4M{^WfKgIbCO0ClFuiMj;=+1-gi$_6dm(8S`1q5!K+3i-l4FL}}RW+f6?>DMwvrBzV0ak&^Kb0xtLXOzrP4`Nz+D1m=h1`IPSb) zS5e(o>7QE^2skBxCjdq+7HoK6ng}MPM$)>LblK^Jsv%hVhTJJ`jp)$nO6oO~rXW<> zVCJq#h_1@z&UE!|UG?;94MW%g7Vu7L@ctVEzfn_G{5o!H}8O;Ts!t#$jFhxb>i zSA3@MF7z=hgNKP+EWa!PZ-ZTRb(B{95(J#CTV4yOHeYiud+9a%%w(n)U4ln0I6SDx+y%Z$_ZTw>2ed5Dn_z#=$0v?@FDxh#gFz|R zyIx7Cr(^vgWCorcVuyu}8^ZaAd6N&2hpeF{bI9FW0Jnd~ z70gx`J^|pO>=`&XaNR&;8}FnBw&Vgj8}T!T6@IC0H`{4$HQOzl+46`u;l@OzIlKK@ zT~)p>5Y2>En1u$Fbdi0`XKOGOsjBTvyd}4c)YHMD4{rpnQ5!_^YYzTW{UGNn%B!e2 z7YHmRmo!D4-PUfRwf6mZ{6<7a)0$ zvH5%GgE8x^=dSbo>T%t|A~V!V|62aaV>x4KH=MC@r+(C(abV)ZFM?3Tai!q8$Q{JC zfK!U;id2c!94^4{nD+s(1f_r2^;I}!W&{e{42Xo;rYq*mm@MG`vr29JInt2s7sK2N z%3#nL5H2V2xp&vj&J=E6T90>FsrB9ZIxy$e&PD!l4GV6_QA_}5LYLOf<GN17rdI`oat-}mZ0(}P36bZybC5#RlN{X^H`$MM${kF4mN}ioK9h9c2}B-} zKf=2xCO=YE;gR52H6E{fu$tKz=qvQ-e%JhSJ(r+h9n78!Fu|9AJ-^@J$yZ*wJ^saE zC_}F=&dTVz_5-%-oCn$M&6Tb&qoq@W*eZYnqQ)hH$ zm}9BxMJQq`O)ie(P05_y27LshWC?}yrII8VLq0VE~Tls5LHg0brf^luU zdaUw{8sKrwe_nOxWH7bpx_kDKAJy>{lnwZ$Ql?%D3&}H;=jzI>uOd8FPD$Z4-tJQ4eu)jEgG!tDGZk_RG0q1yRm|JW%VimpzapI^5I zn(Jh?sVD`GjX=ZNPKU2fC8RNrD0cn?HsiF$iZ%~)1~36a1WxKamMvxV*CTeR8aD?d zC6<%R)5C-fBtksoLU)@M?FUX3kb?5OD-+>NdM#IK=X&P#DcJ3lOUnuNHO>qH&i5vW z5(4_hePToch3Abx+RQ~x+u*2A!p*6~#wynTYo-_D+)y2{&P&aE4F%bbmI5a)Pb7pd zHGKs9vK<|)>(!G&QzZbXq&E3>&CuRP?j-5#(H>;)zgmFWw4rExiA-0`#E-Y9AFNmg zw~oP8G_k}=Dgv2ZZD(o!81GQ2jlS8vU3lz0>(yVJz1^?#k^2bSxCNp|nv4;sv`8?K zOH*s?D&@2Yltfktw%<7pquayb8y%oRGl}|LSz#{Id2cuVr$0N7WR6$$$S8qr?VF!T zm4UuzqKd>@$Ujr5R&8ueJs>9K74J0Zv^_X#{j&_i++2|VPOBZiTfCpu+SCn}f6RSWB=3f(Jpwh|kn+ernVsWuw16J>`oaL7>OZ2uHY)IzAN|`%O^r zB?uk6#&O5%Z_lo+ zuIP~xd&iao1=UIefvn-Hyb4ut?unld8tml0C5#Y^D-jJjoIhJC?<^EJsjBVAu#hY?y(K16GGrbhc^Qe!{PXJC>5e}PT)dm^UY2PdRgoE@)q2U zVGEr(JN{^x)k4j9Oy+?&3U}ih>#$Gsw<=0VcwV0H$6HO9l?utoOy5{PGVzrY;sTvI zd@w!#{NBe)k5{-Mnu<~u5`RYmCFEki4t_z^Dp%t-d4OAYzA@b6`A*8hZpK86MQMmY^qs+#=)5~TI~;(0 zyD@p0KjZ*XMNN`VF8L5m1>)#(64w-O)iE!w9(2s#o5!aGgN%C(9|2Z-%iz*7{Y{$S zqw$_^dDjMdqmaj0OZh5;LdHoO4% z^Q?Y+zz*E456&QdcH+b-4aIqNTlC@3&GAxU((AJ{#O*C(X}j)3=$(~2(^2t1^muzE z!OJw1W&eW9o9+jyT)9{3x2zqdVGPNaB?1?s*g*s-*G}D=#t}_##Qused$v@I_(}F9 zBcFb{lh}$jU#L+7S#B?FC4bVN*vT(jm!HAPu5MUp#KS|;r6b{R8z0DEE+PI@PZ`j> zU8esdj(OxGbzub*PJWZx$!zG&47^ z-cE3u&8|Ssx+Vd8O5;=;`Mr&PtyG8MIydKI@^#?nLX(q|MrR7g zH8fmdTe-C5Wu>KBnGsbIj1CxJ##DzfZw8dNTB){|8v?bb0enKSR+p9SF|67M;J?d*{&q|} zc`=dg*TgfRO&0{jblYHVK{9kC=D?Lqq28}l-g64!r#jiB@W=JQ@c$B)r@N0C1ex$OBJMl;kVu$hJ4u|U3;X3 zXDkdC=)WrOfB!R)ErFV!ITFZt)%U!2!pKA&e4Yqe;kf8myJ4$`5N5G&{3onyZoBki z!sTFs>sRID<3pzB#5#wumppbNw(P0v`NCG}EMat;^M|V@qCAd6x+A<@Gzh?3K&;aRJ1)h zS|1V_9k3j}^Vzq>amIqs&Nv+)3)u6^@1+B}!BOvlV3f6q*;$Y3d`B9;J7K}%I7Mst za+smok{*??6)PiSWoLtu40`{)`R83ly`23XS^pS2IHLHt0bRB$ z&k(zMh%k?OP@9DigK8CN6t``mX>CozBjk9*!Fjt zaZqj7u&NztbUOxPIby{+(Glr?#?O(2y7Sr7DslyMAX5~rTwPtO=Z+oi?Mq(h*xkWI z4;AY?#%{mt;>-_yD@Ftt04|wl`lk3N3oQ}+!#txP!*@jbwfUUNXK-;)Ms^l5kC7hn zIlIfE_K&0JQpUrQtxu>x1d>g>U}1%Usq>Li^1txYEd&KteqyE)1lQ{XawhmYao2i5 zXI+3B%?tT0i(K?{1?bZopdC*@_*gX)#ROpQ`l!V>Qf=-)BkWQ{d2Gd% zTw6)AZcInq`p8yMhx|J7*P5yt{`Y@?yF2g>Tz&7@O&UptOGWU6GM#&wjD|i%w*{7mI2= zou5b4OyONCMeLhJXbG2Ua_ zTINIFWk*adWz>Dzu$UO}88aVCURYXNkrI58`)E zv~LVH8g&#|bcfiYA39jF9)UG!ejUm2P)XPzY6B6X%=KnhyQX&CVobcI zcHd$e>4{9YtWy#DtHnbaoj*I`Ir~E^mlPzx>Hy*0%7q9Q4ac&D)Tf(5JXI(AEG82ptJ4N) z+N;%6hoDpp!*@cl^Pr|-B{(Hs&cEd>UlAszd#|KHn5cbbzp)zdA6b=>O1D}$5ES)@ zn`I)lO3k&lo9F(aVV#^eSlxt=|9I619#L|#vxrAx&V>GXp_xRHha&UWM4HRy++^Ob zw^LE&q>6XM1W0mqk7Yjq>jGi0=4nl+X~ki$gn-DPvJ|2WJXM*@&CKdH(tA!$P6p`c zppL~hN&(TUVVsuJ(e`suBRnM~ zr4e?Z%4We7Srg{mwNr*2+^zMO59198;6vGURyT=C-5}UQqrA6bFB!py0bT1wxq>2X z6AR1j#f6DYrP-(J9^j_Lf{SZUezLMEU}9yRt#?s=+oxYrR_bbMTOam)aTsyOvbnI{ ziql7&?FLzktCs+E(zfjO>jSzZ&TB7*@I_10C6h)oQgQ`&QZtVtfgK3BONKY*AIp1Y(0oyOm)1P`H$g+^)07B%0b z$n(^T2*s}H;V8K(7hkt?>Ub3ajFl@Xux$9Z{C&9u1^>pU4nMzs{FgR~v04DPC=tPX zU_)14NgGF(6)u;%{?33G`Y6m+gWyKZPrieMO2E46}PUsP^>B~jV z%kN&_XW3pakkZjs46;hvv$$L?77?vaOpr6sMwvg9Vswu#*-e=p^>O@t)@9^&8EoNK z+B$e`sbGqad$mZd?BV|C@45Z?!|8vSlz$wug28)~3ZNl$+P0oMf%E`OqlA77u9$^K7X&G+n;%!k|r_fW$|UC z%dKbhpUdA5_GGO01z46DF${@WJ8(jv#-#m;l1VwEBnqvA9en$Ybi!Xha^ToBto|9=glQJ?%J){i9Uo&tcB*-=Fy5T0n0>b~XpM z(@4?p`-Kv}aR6qeK0@x>y!IBXfx!lww!b@wmTyXKH|zUH$8)q*(Z(w*)ns5}iC;f<2#^d?PK@JEKOcLy*#YVr8pe<{ z=)782kxX6;zRUlf&ep;KWK!N{VMyAHp_rgrzXzkb%vx?0FkeG~QvoJyOiWd6=C020 z+wl38Q4kZW)L3e^vnCc$0#yk#)B@l2|BP#Xu2E5{3DgJbfAZO_KF6VZLwc*d+x)=K zPcx2cpv;}53Zkfq1J46`3z;_w#sY_j-B24Q07oDuJ+q|dF6+8ARanY2%MX*OI;<6- zv*@=LVAQrdYpSLqzVT6PnHv8wNj*hGMj$2Zzz!r!WI=+-cOoa%>wm)KGk=Yx5jqT& z7}|t~;D#)&qJG9|cmm`Thw8x&UgMut`)zr5X?*Ak8$3Cg zvdTpydDf+6XRnik#Gh%!u;f2`1Cv*Wm5<`byBpWH5g?nLp|Twh7Zmsz;>+~Q>U}kb zbvb}G=Vj?H`QF^zJfH%E{_7s%pXvAiOSG7)KoDd{$8gN!HxcqVx;w>+D@z_BJks;m z4*7?t({6ZG;9mEWbj|3Mb$#u{>3RC=_A24wv>(AUBMI#k-Tf!$xCKv$WUiN@Zf-j8 z(E}2cq_SRFqNdaJACmf>3w>BDg%FA@ivZKHRkaRFZ-zzA864|RVd|p=^5<%29ieMZ zClim{*3%itIGWB<^#MEaG;t6fOZApO`=6Fe)QIZ;@w`A=rl1ic934pfDl(>oskyeQ z9MHiBBtqU*d1^>Nxo4fIHg1ldN}8KT*BAW#%YHO9*S1G>buXu4{4A9lKs-y==2UP} zzD<^H1y`2orIPR1bzT;0TsWg5Dgph=Yp$0Bp_G6yU~QtWA@Pys7NS3?*?%Kvam;tD z{G)CO_qN?;x(2sFK`Q$p&dM9yf8~7bi%OfahUtKazWu{jgVvgWzi-#nYKHz z#?4XYaLPBY<8Mb_Scw+Fy`3Dz|>S)VSSxDhk&VULG8bJ-$91 z3B3O;V+V;IDYe#eP4OYs%}a^bUWhkSWTb_M6UItBI$M-6rPHLBhgn`@No6NEoR1L3y0L?Ng!)|VMCWt05uSjd0l()}#=C~;s(uF;2WZU6`TE1w(W~m zv#h7I0LL}Czt#9tGPito-Le5CbbXK+*T`*(By%(2#GC!}?+KJViZszdqFR)c757H7-FVJ9egqJ6~^4LMHm}@ssWr&YQD< zEMKbpu5X+;@kW(mOQy*{aO;a$gidNp@{5kttk8LV%kR#x=cFf8-}SOZ%x5a_tF_(m zWuK`eTTF2SFV~YrvmWu_UiI>088-W7n%fe>hny|H1pceoUkd1l6fyTZcEi&*AIz9C zOG7jvy0ZP=1`VI8jSdbsSL`&vYKd?4OTttQX~_ZBjmw*f=Ja~*cs_A{WI`HV1oSkQoea%@XW^YO~{aXj75o% zL2^&aai&V@p?zyhvK>=Rtq-AIQZs+wYcir&dYWkvKv!*45zG?G4fNsBF#7%NiXGfb zG$514z1>;X?Sgh3K^FXFW`Sqj^i*UeXyT0y#ZjFHp>92ExNg1Ndhd!lVLhF8^BHBL z73;yFiIXVSHgLb84|0UEmu0BN27xP@B`I#0rVj^7W$!Yk3l~K2vt8ftFr`0aOjidQ zihid9*VxI%uC5n(joWWb{u3l6h2Vr|oFA;GW9(b;Ya$(|xR#UVHRC3^c36(JIC?KS zr%;hz2oVTk>k4RTG*X`1w*%I2*-LWtf{i-Jf*kz?;Q*OP_IH@#QO?mqpCE z3=ac(ysjix5mAPDc2lFbuqI>=3t$32E@pmaf3eB)uP;{o7PHoXIxFy{*D+->)VS=7 zLo(-UUABX&iJ39ww0t>P@a1Q%dr!!zAr%A-jKC;zV`LMzAnTcp>u@`I9q^e^O31%;YAeA9Z*p zviBVR>*8d)`mJiU!X1SLMq=OnI@ybliaV`J+aG-*>vyumDBfnyLDa4Zo|kHV)VMG2 zaCn$5sm&sfz-Pw%0tUcfGes1Q?#+HcBV}bk+bZ3x5q1L?*y=Dc?nwLJ;ROSYVfg7x zO+0U6AeT?lN5LAZGrh9)^$zZP{5QQpL*pt`g%r~jC2h@DhwEsV7n03{42m!N?O{1AKm5y_`mGLS)a0z z6n00hZ=P0MT|S@Md3-Tt((&i#)C-Q6nrPsJQEXr%!a5Dieemj2<5%=nUh8qU(H@?; znoea3o;kO}hv~x>`#*Pn=jJ|>MONf*;L!YMRf(S`-&H57ns_DuBG5m;ZCvR~)B{5c_&*?@M)2Las% zV9B>ie3^Az`diRciRn<9<|dbxj?;gkfb(DFc4g#2>jb;8*ULo!c%*jw{{pzn$>k&P zIi|K^c_p4PrEtGYd-VjC4tuU3RwjAkD0p*u7zp;}gn<9piG_iT2R%MtXP*mlYhq}*OdDTq$*Hz` z?9)FN51S3#AnwQI)J+w+nZ0WlMln~kMSp^l5^5T?&J+X4n6tqSaQU=K^FTzWY@|7ob1KK0G8ATZ4D!H)~RHH%nayv1;9GBR3Z_xYloN;$8obh@rdH{H0x{%Ff;gXH^iu39DpIhFk z?iX02ecNhsdnr<8e~TR%0WQd6lYgHq@Ugxb!y;kVKvs2eW6NkxkC?)?A`kKbwnZsc zhVps_SQ5$}CR`iJjk1}T-=2dW2R2L8cFnPEYkmC_jnl5DLmICx{sP{|m_BQ(p;2~> ziH3KxsW)AFWVtn2p4&CIJC;gCpCtTvPH4aST_^el2#(!Wq269S0`J+&t3EWLeXCAY zh1!kj#-e!U4}^CT#E>P^+K)i>%4Y4y>R+6l^{m=$w$BBBI|Jy?jx_a*pCdKxaL05kt+EMcjEZFMK&cjb4gA;nVF?^Q_mvW|R$OO?0%Z;v#+0h^s z&H6PL!Tm-;zEX#U0TTV*=+)%k72P1h1fq6_$9c2t2r?Ksb?o*UM(r*=l;OVCHcjzy zMzuTkYsBzwc93ZOjvk2jL`}0EUb*w~69RkJU?B~n7Z3R4<_w*^I&RO7BlHz_SXZ_> zwi~(4IOg|>gFjBb7y{cn?tpm&#;QjDnIdmYJPO9?3*y{oSni*L0$zMFE}J#{%Pn(R z^Nvl|sjW0V>D3t<0;C0qATjIHC!Kavd!2_D^vJAejdZL>?#xIR6#2f)Ndi^T z!E#kuegWe1X;|Er>Q#g+0#kw{gGI$SaW@4+{{8%{xUs`+DUkv1=05CJ4xG2S2o|5m zvLIomFanSFafsXIR#W|d4pdP3T9xx%}13n3!kRvePHG`8~v>YHU9ir1;j;uiHk$q zzC7Dd{cOtm)=YyQT$Q(dtzi4oVI?f`A9Vk~cikM!05XTXiHn7F@wc)aGgMEyRP;d_ zyMftyrTXhKhy#H+nqf3@{l)zY#f(LJdwcTH+1a{T={O1s3TsDr8JET3pk^3I3@If^ z-*Oh~l`(9G4#KKw2k7jY8cRea3^H2ZnT#}I2$Z&)o=c+ezGE`EU5Z+w_gm-c#R;IN zM*H)D8AG=?np@o95xLTR>F?89wl3+d>2Hy;V2=u(F34vvnw_DT{6B46cQ{<#_CCar zj|fqdAQ3@~Xp^W>1|f`Y5JV^XAbK4o`LqxvM2SSnr;7-J=qvT1=`P<;_{fQB;{@|j)=Fqn zWXM3k*xgM?eJ90Xle&xf?cf)5-hP*O+Ge<=N8x;%$x~T8f`VoihDmueKAxU_iJ@=#}2(gEUMRMaH`t#Q!I6LLch>SjX{3P!--Ydcf9{m>IP! zZ+VNN+X{ROQSZIO0&_FK4w03|npm^qOZ}aD*gx?1;q|v)-s}6C{x^-FEAC^$@mH3dh{C0k5o+Y+7o6d zvIG~SMV7td-sCTJkpchl#^=4slqy*tmzFy4!ARKTvcU^Gwdyohk1N^9X}6UDpflmiH8Z~KmhujV?>{0or4%^FzYO6L@AlnKM z)nZhcpFzNsS9r&q28E$8Q6_h9mP4Al5?7o2fz5?Vcx6JJj%T@HG>e^(z5FJo@+ zyAgG}VWMDX2NryW)6(aDzgiFKGI5>Ov2)p1?sy*e+<7JbS8U+1w%P+v1h!HpJit+!O^35m>7CT-dZ8UT(ixS;?( zSzUI;$aFT;eg!@1^=A_Yf>O0hhILhk z(kQ1X%BF^xF4xwWR%YJDIQzrdCUCGIs#S@bZx-d=lz&2tU;P#M9vZr)VgB>mvtz5c zI&+fp;X5KmcM>Fy3Dw19INBD^bxyQCVzg%wD|2)2N`uf4-AN-Ghug=9kBpl#4DnV5 zf`8bCNAiqom(#n93>qWxRE*xoW$qaT?e#zXA%}LpOEP3__|J;b`+2k{Xe%8n zgIVwwN{zTg7vC76+^eX>!OcOX@YI}P^;Mf?nZt15G#-y{Jt?eeXb2oD)GPApuyp=q z-7pQ}Rm7-(A(l+}8|->585)nTek!$eI~y=TC5*rA8G&X<=2=|hfxLhC0G#wdkMGCT zW+qOM&tW;-t_K?eKOXI4#M;cwvbSt>VhM9ws}MNW5lc}fO~dgdpi+{ zfsChiR?L9>tNR&YGw6&AP{^Jr`zV*|_=V3ASfjZnb9%6FlZlb>J*X=0t@0<{K)2Yk zUzc|vpBU?|gJW)N8DHztl3;veZe@eSQ1Zadp8pU`c&aO|BZJzet z*)(>E*)&Fnz0Of(!FZ-XH3*g4%a{UtJDoD0OXZ$-(oib^oE#x1cu`&ewAK98bzv2# zqndjLj!o`-UTb4p_s7DYCPykar(gYX&V-~FhrluZWH83wMR%L~2NsnZ2e8k*VtEuM zKqw6;O)>Uc$zf9|fP!q%AQ;dzU-5ms+?EFN>;h3wQOZ{|?U<(hhf{fS;M&mPaWnn) zn*x`5%NWvaQ7;o;#v zP;at&jD+<9CZKY1&{m00M>of7KR;f-Nr#HU32?`Of;9iCuv ziUU&+xv-rQ1w-?W?ZIKwjvwqA+WM}4sGi8WRPg(*hM$+9e_#k4Zzd z7ShSG0VFu#wK_Fw-uEX4SO4aC4oXS*dY(|t37jJrq3Gcy;{tFhM6>6(9YyRXBZgLq zf11)Z%KS7SH4?X}99}^3B8{s2-sBpYZ@-ZVcdN{kFW28Q|GY}GgNaIg5ag&A6RXK8 zl8`t_M^-D0mYW9<8Ac>1G91WaHQeS`XGuiu({c~E)%io{<47!oG{ z3U=n00C&=<*w23mP?wXGnZ?og%k)LHz7icT#=ZEvF?}G_YHlu2BU58@6adpvnkyr; ze5UMD`i^`Rd#2VD^4b*)T(mSCG0hng2E;+H#zc1V0xqN}By%W0iFBEKw`j0>`pY=>5a;D|!zL|t6!l{6oqW~x zaZQQc1)kTDJ8@;#eE37854uJMw`OlqHiGe3dd@R-z9nD5MRaaG2!%*;{2MFGVdZLA z7xs<%Rh1nXlhKuiu=tcbzFIW8h^eaWD^A9UO7kd-RebN^PxGsnvi;W?^~rNEs0~tsF$7C~XtRmBZ)ARmH}=TfOIfRk;?{d0KZtti5%EVMPkoNO{y3n+gyx zoTO$9vok>~!J=NQa^n-Vx;`5t_ zY9S3Vb#@MS{ezQM+R-*YTs?lVF|#P;*kccZ4mqn2};5U-`D95{1d&N zmbmQp(piO(Hn&imexV z=qGZ2ja2pIVp{t^?U7X~nvCT6!X6p-g+*OuNPg-f_rPG=Qx7+KmyOM_;Sn6l~XUOIbq~QE|Mb^*-s)&R)0*s@uCAk2-#W!QkBAbZZ_J(QHzEUKTNGd`PuDqB`NVE-lBJIw zxyX+vKReU5h)?(;8)4eH`fFM@ZJNGKtxKCdXFnvn>H}MO*@wf@(%x4y@E}tgYp%d$ zHmhF$RF*xOEzhU}(!*3OakG{R7rdoN0ZFlDOAQ0}5n{G_AX<(wp^4t;>=p0vakvIA zpGqEsOn5RQd%ycVze6g+^1_0Nz9KFy_8f1XhH{Uc-1M2ojOza1p%DJ*CshZdS+8V_ zT)&O-|DsxS)R_Og*3*wOuFfP?1oGN_><(t!ynB9- z48E@`hh9A(3=*vpLkg|e{3Xe9iC<-X>xgV8xT2jPM|``oFuylwWo<)aT_3nLVlSe2 zw(xVl=Ih_!WPZ1T45LWT6E}d3-ju5LAAQoQnVZLwUZhBCRuv(r^-eof`hxGS&sSPJ ziqmjFOz_)?i!Yw6CeFitrHH8y-C=1&3qdlKeDi*ML%M7Px7`|!4}St{=4^1jVwP#( zPU(M<{I|Zm_=oL%6s=JszPkj&ox?(T_@Zqm$f}e-f)q+MDH!N4aB&2G@2sjH!y9u@ zqZkn4mJ)Zf>m;JZWgq=EKm$ei-Se#LZHsMkZvOj(_x`L1-#}ro1I)m;-dDbtECv(b zIqDO#Adat&U;L>a`TDSonuaCutV^;KuQML5dYSk57oDL#&ZtM&$@@ z4}H8!Q(^fWasHYl6kA(KLuW5B$FrL1rlgP;j!-&$8-ZK13S48XtV}nXxD_fgZbYE* z1WnYk&Dw8nR*gLKH!~w-dGzrUd5t6 zz~pd$ms-e*4+ycc7v8~WHRTUMp(D!uaC_+2j#)Ji)w0lkOH^_ms; z){qYaNf5KK9qpZ|sjh1F&kiM-_ng~*vRJU-~FxG9w%v(TYaHSYRL z0qq7wm}NWvv^wv+Kz^J=sPx@DhRf1Xm6^><=%t}m(JTjMCFNjJXxb(x;X3@M?^5)G zurNBYA((LXkHI`FjVAQu(LZ`uh&>JfWZA;Tte-~vst>rl9{K20CoEBL*x#>?@jy-1 z>ia)>Bzm+&Fhksg$l;RPdhnOeeG>S2&-ijFi*{%dYo2Ub)78N{D|Zk^qpU%DYN`nd zegW8|^xj^(!{!T!fsyIjiuzikbpm0ce>Bg$C+UbgnG4NC*1UdX_J!lT34u(|O>ddC zro@dGn=zO z=)irg8?BW7)}pHg*B&1(9pjKb#0n#?iViKDTA>r(BHuotAS}ePSWjq1HM|wtH;CMc zX~m0hdaMWpQ`Y+@HTqO?X-> z>rg2~ED2U07cdaTelMN&7mi!mAlhPYZ^zXfjM&K_Cqmf=-cf-?0A0BWy9lrG_C_%& zv66x@gR*u!gP=KzS;>B;nT&V}b+v)s4}AO22gC!7v2hPb)9;kx?zHO_7FSiU Q4FLe5sG;yl-u(Ih0nh0_wg3PC literal 22492 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 Q2h>*dw2if1YB)sy2ZDsplmGw# diff --git a/docs/src/assets/logo.svg b/docs/src/assets/logo.svg deleted file mode 100644 index 5ad73cd6..00000000 --- a/docs/src/assets/logo.svg +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/logo/make.jl b/logo/make.jl index dae4101a..dd527de7 100644 --- a/logo/make.jl +++ b/logo/make.jl @@ -17,7 +17,7 @@ end site_coordinates = hcat(site_coordinates...) site_coordinates[2,:] = -site_coordinates[2,:] -Drawing(840, 300, "logo.png") +Drawing(840, 300, "logo.svg") origin() translate(-460, 110) From cb48092f5c50b798849c3935b95c2b0d6543f0a4 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Sun, 30 Aug 2020 22:27:49 -0400 Subject: [PATCH 04/13] Update logo/make.jl --- logo/make.jl | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/logo/make.jl b/logo/make.jl index dd527de7..5dfd2a45 100644 --- a/logo/make.jl +++ b/logo/make.jl @@ -22,7 +22,9 @@ Drawing(840, 300, "logo.svg") origin() translate(-460, 110) -let ratio = 88, radius = 10, radius_large = 14, offset = (0,0) +let ratio = 88, radius = 10, radius_large = 14, offset = (0,0), + sitecolor = Dict("A" => "brown3", "B" => "forestgreen", "C" => "mediumorchid3") + sethue("gray") setline(2) for (i, j) in kagome.nearest_neighbor_bonds @@ -34,12 +36,6 @@ let ratio = 88, radius = 10, radius_large = 14, offset = (0,0) :stroke ) end - - #sethue("white") - #for sc in values(site_coordinates), r in eachcol(sc) - # circle(Point(r[1]*ratio + offset[1], r[2]*ratio + offset[2]), radius_large, :fill) - #end - sitecolor = Dict("A" => "brown3", "B" => "forestgreen", "C" => "mediumorchid3") for (sitetype, r) in zip(site_types, eachcol(site_coordinates)) sethue("white") circle(Point(r[1]*ratio + offset[1], r[2]*ratio + offset[2]), radius_large, :fill) From c54f9b8530fec2a4e5f039351d4130814a9f9dcc Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Sun, 30 Aug 2020 22:36:41 -0400 Subject: [PATCH 05/13] Update documentation Update documentation --- docs/src/Symmetry/space-symmetry.md | 42 ++++++++++++++++-------- examples/example_group_isomorphism.jl | 1 + examples/example_honeycomb_symmetry.jl | 7 ++-- examples/example_hypercube.jl | 1 + examples/example_kagome_symmetry.jl | 8 +++-- examples/example_little_group_2d.jl | 1 + examples/save_point_symmetry_database.jl | 6 ---- src/Basic/lattice.jl | 15 +++++++++ src/Group/finitegroup.jl | 2 +- 9 files changed, 56 insertions(+), 27 deletions(-) delete mode 100644 examples/save_point_symmetry_database.jl diff --git a/docs/src/Symmetry/space-symmetry.md b/docs/src/Symmetry/space-symmetry.md index 1f666240..f1f28413 100644 --- a/docs/src/Symmetry/space-symmetry.md +++ b/docs/src/Symmetry/space-symmetry.md @@ -1,4 +1,4 @@ -# Space symmetry analysis +# Space Symmetry Analysis **LatticeTools.jl** provides functionalities space symmetry analysis, useful for creating symmetry sectors of quantum Hamiltonian. (Check out [Using Symmetry in Exact Diagonalization](http://kyungminlee.org/symmetry-for-numerics/).) @@ -13,15 +13,23 @@ Currently, the only type which implements a group is [`FiniteGroup`](@ref). The elements of a [`FiniteGroup`](@ref) are consecutive integers from 1 to n: The identity element is always represented by 1. The following example produces the [Klein four-group](https://en.wikipedia.org/wiki/Klein_four-group). -```@repl -using LatticeTools; # hide + +```@setup group +using LatticeTools +``` + +```@repl group g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]) ``` Group binary operation can be applied by [`group_product`](@ref) -```@repl -using LatticeTools; # hide -g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]); #hide + +```@setup product +using LatticeTools +g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]) +``` + +```@repl product group_product(g, 3, 4) p = group_product(g); p(3, 4) @@ -29,16 +37,25 @@ p(3, 4) Given a group, a subgroup which contains certain elements can be generated by [`generate_subgroup`](@ref). The function returns the set of elements, not the group structure, of the subgroup including all of the specified elements, along with elements that are generated by the group law. -```@repl -using LatticeTools; # hide -g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]); #hide + +```@setup subgroup +using LatticeTools +g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]) +``` + +```@repl subgroup generate_subgroup(g, 3) generate_subgroup(g, [1, 3]) generate_subgroup(g, [2, 3]) ``` A group multiplication table of arbitrary objects with an arbitrary operation can be produced using [`group_multiplication_table`](@ref): -```@repl + +```@setup multiplication-table +using LatticeTools # hide +``` + +```@repl multiplication-table group_multiplication_table([[1 0; 0 1], [1 0; 0 -1], [-1 0; 0 1], [-1 0; 0 -1]]) ``` @@ -83,7 +100,7 @@ In some (not all) cases, a space symmetry can be decomposed into translation sym In other words, if there is a point $O$ where every element of the space group can be written as a product of translation operation and point operation about the point *O*, then the space group can be called symmorphic space group. If no such point exists, then the space group is non-symmorphic. -This can be written in the following way +A symmorphic space symmetry is thus a semidirect product of translation symmetry and point symmetry: ```math S = T \rtimes P ``` @@ -160,6 +177,3 @@ Translation symmetry embedding is | TSE | | | | | | | PSE | | | | | | - - -## Symmorphic Symmetry \ No newline at end of file diff --git a/examples/example_group_isomorphism.jl b/examples/example_group_isomorphism.jl index 53973e85..4ad3e132 100644 --- a/examples/example_group_isomorphism.jl +++ b/examples/example_group_isomorphism.jl @@ -4,6 +4,7 @@ using LatticeTools using Formatting + function display_matrix(io::IO, matrix::AbstractMatrix; prefix::AbstractString="") width = ceil(Int, maximum(length("$item") for item in matrix)/4)*4 for row in eachrow(matrix) diff --git a/examples/example_honeycomb_symmetry.jl b/examples/example_honeycomb_symmetry.jl index 1a4eda61..662ea3ba 100644 --- a/examples/example_honeycomb_symmetry.jl +++ b/examples/example_honeycomb_symmetry.jl @@ -6,9 +6,10 @@ using LinearAlgebra using Plots simplifyname(s::AbstractString) = ( - s |> (x-> replace(x, r"(.+?)" => s"\1")) - |> (x-> replace(x, r"(.+?)" => s"[\1]")) - ) + s + |> (x-> replace(x, r"(.+?)" => s"\1")) + |> (x-> replace(x, r"(.+?)" => s"[\1]")) +) mkpath("example_honeycomb_symmetry") extent = [-2.5, 2.5, -2.5, 2.5] within(r) = (extent[1] <= r[1] <= extent[2] && extent[3] <= r[2] <= extent[4]); diff --git a/examples/example_hypercube.jl b/examples/example_hypercube.jl index 7b86e04b..fc5aa2a0 100644 --- a/examples/example_hypercube.jl +++ b/examples/example_hypercube.jl @@ -3,6 +3,7 @@ # ## Preamble using LatticeTools using Plots + mkpath("example_hypercube") function draw_hypercube(hypercube::Hypercube, coordinates::AbstractMatrix{<:Integer}) diff --git a/examples/example_kagome_symmetry.jl b/examples/example_kagome_symmetry.jl index f195d143..87ac3260 100644 --- a/examples/example_kagome_symmetry.jl +++ b/examples/example_kagome_symmetry.jl @@ -5,10 +5,12 @@ using LatticeTools using LinearAlgebra using Printf using Plots + simplifyname(s::AbstractString) = ( - s |> (x-> replace(x, r"(.+?)" => s"\1")) - |> (x-> replace(x, r"(.+?)" => s"[\1]")) - ) + s + |> (x-> replace(x, r"(.+?)" => s"\1")) + |> (x-> replace(x, r"(.+?)" => s"[\1]")) +) mkpath("example_kagome_symmetry") extent = [-2, 2, -2, 2] within(r) = (extent[1] <= r[1] <= extent[2] && extent[3] <= r[2] <= extent[4]) diff --git a/examples/example_little_group_2d.jl b/examples/example_little_group_2d.jl index b5d2de8d..a800003d 100644 --- a/examples/example_little_group_2d.jl +++ b/examples/example_little_group_2d.jl @@ -4,6 +4,7 @@ using LatticeTools using Formatting using Plots + function display_matrix(io::IO, matrix::AbstractMatrix; prefix::AbstractString="") width = ceil(Int, maximum(length("$item") for item in matrix)/4)*4 for row in eachrow(matrix) diff --git a/examples/save_point_symmetry_database.jl b/examples/save_point_symmetry_database.jl deleted file mode 100644 index eeea7bfb..00000000 --- a/examples/save_point_symmetry_database.jl +++ /dev/null @@ -1,6 +0,0 @@ -using LatticeTools -using JLD2 - - -POINT_SYMMETRY_DATABASE = [PointSymmetryDatabase.get(gn) for gn in 1:32] -@save "PointGroup3D.jld2" POINT_SYMMETRY_DATABASE diff --git a/src/Basic/lattice.jl b/src/Basic/lattice.jl index 95f63a09..200f9e66 100644 --- a/src/Basic/lattice.jl +++ b/src/Basic/lattice.jl @@ -31,6 +31,16 @@ function Base.:(==)(lhs::Lattice{O}, rhs::Lattice{O}) where O end +""" + makelattice(unitcell, shape) + +Create a `Lattice` from `unitcell` and `shape`. +Generating translations are fouond using `find_generators`. + +# Arguments +- `unitcell` +- `shape`: shape of the cluster +""" function makelattice( unitcell::UnitCell{O}, shape_matrix::AbstractMatrix{<:Integer} @@ -100,7 +110,12 @@ function makelattice( return Lattice{O}(unitcell, hypercube, unitcell_coordinates, new_unitcell) end +""" + makelattice(unitcell, scale) +Construct a `Lattice` with `unitcell` having shape `scale`. +Works for one-dimensional lattice. +""" function makelattice(unitcell::UnitCell, scale::Integer) return makelattice(unitcell, scale*ones(Int, (1,1))) end diff --git a/src/Group/finitegroup.jl b/src/Group/finitegroup.jl index 238d4360..4e22ded0 100644 --- a/src/Group/finitegroup.jl +++ b/src/Group/finitegroup.jl @@ -45,7 +45,7 @@ struct FiniteGroup <: AbstractGroup inverses::Vector{Int} conjugacy_classes::Vector{Vector{Int}} - """ + @doc """ FiniteGroup(multiplication_table) """ function FiniteGroup(mtab::AbstractMatrix{<:Integer}) From cc553677c69e88ad8646da219c7eb73c121a1d1c Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Sun, 30 Aug 2020 22:36:13 -0400 Subject: [PATCH 06/13] Remove unused code Remove commented code --- src/Basic/basic.jl | 31 ------------------------------- src/Basic/hypercube.jl | 9 --------- src/Group/permutation.jl | 13 ------------- 3 files changed, 53 deletions(-) diff --git a/src/Basic/basic.jl b/src/Basic/basic.jl index 3bc33471..a8ca35cf 100644 --- a/src/Basic/basic.jl +++ b/src/Basic/basic.jl @@ -1,36 +1,5 @@ export ExactLinearAlgebra -# COV_EXCL_START -if VERSION < v"1.5-" - function Base._round_rational(::Type{T}, x::Rational{Tr}, ::RoundingMode{:ToZero}) where {T,Tr} - if denominator(x) == zero(Tr) && T <: Integer - throw(DivideError()) - elseif denominator(x) == zero(Tr) - return convert(T, copysign(one(Tr)//zero(Tr), numerator(x))) - end - return convert(T,div(x.num,x.den)) - end - - function Base._round_rational(::Type{T}, x::Rational{Tr}, ::RoundingMode{:Down}) where {T,Tr} - if denominator(x) == zero(Tr) && T <: Integer - throw(DivideError()) - elseif denominator(x) == zero(Tr) - return convert(T, copysign(one(Tr)//zero(Tr), numerator(x))) - end - return convert(T,fld(x.num,x.den)) - end - - function Base._round_rational(::Type{T}, x::Rational{Tr}, ::RoundingMode{:Up}) where {T,Tr} - if denominator(x) == zero(Tr) && T <: Integer - throw(DivideError()) - elseif denominator(x) == zero(Tr) - return convert(T, copysign(one(Tr)//zero(Tr), numerator(x))) - end - return convert(T,cld(x.num,x.den)) - end -end -# COV_EXCL_STOP - module ExactLinearAlgebra import LinearAlgebra diff --git a/src/Basic/hypercube.jl b/src/Basic/hypercube.jl index b2cc01b1..870e7b0e 100644 --- a/src/Basic/hypercube.jl +++ b/src/Basic/hypercube.jl @@ -74,15 +74,6 @@ function isequiv(lhs::Hypercube, rhs::Hypercube) return true end -# function isequiv_old(lhs::Hypercube, rhs::Hypercube) -# det_lhs = LatticeTools.ExactLinearAlgebra.determinant(lhs.shape_matrix) -# det_rhs = LatticeTools.ExactLinearAlgebra.determinant(rhs.shape_matrix) -# det_lhs != det_rhs && return false -# inv_lhs = LatticeTools.ExactLinearAlgebra.inverse(lhs.shape_matrix) -# inv_rhs = LatticeTools.ExactLinearAlgebra.inverse(rhs.shape_matrix) -# return all(isinteger.(inv_lhs * rhs.shape_matrix)) && all(isinteger.(inv_rhs * lhs.shape_matrix)) -# end - """ find_generators(cube::Hypercube) diff --git a/src/Group/permutation.jl b/src/Group/permutation.jl index 5237d28e..4aba3d02 100644 --- a/src/Group/permutation.jl +++ b/src/Group/permutation.jl @@ -78,19 +78,6 @@ function Base.:(*)(p1 ::Permutation, p2 ::Permutation) return Permutation(Int[p1.map[x] for x in p2.map]) end -#= -function Base.:(*)(lhs ::AbstractSet{Permutation}, rhs::Permutation) - return generate_group(lhs..., rhs) -end - -function Base.:(*)(lhs ::Permutation, rhs::AbstractSet{Permutation}) - return generate_group(lhs, rhs...) -end - -function Base.:(*)(lhs ::AbstractSet{Permutation}, rhs::AbstractSet{Permutation}) - return generate_group(lhs..., rhs...) -end -=# """ ^(perm ::Permutation, pow ::Integer) From f9401bbd942e45c5cae7ca0429f23d83a5d5ecc2 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Mon, 31 Aug 2020 11:30:20 -0400 Subject: [PATCH 07/13] Update documentation --- docs/src/API/symmetry.md | 6 ++ docs/src/Symmetry/irrep.md | 38 +++++++++- docs/src/Symmetry/space-operation.md | 3 + docs/src/Symmetry/space-symmetry-database.md | 5 ++ docs/src/Symmetry/space-symmetry.md | 79 ++++++-------------- docs/src/index.md | 4 + examples/example_group_isomorphism.jl | 4 +- examples/example_little_group_2d.jl | 10 +-- examples/example_point_group_4mm.jl | 10 +-- src/Irrep/irrepdatabase.jl | 4 + 10 files changed, 88 insertions(+), 75 deletions(-) create mode 100644 docs/src/Symmetry/space-symmetry-database.md diff --git a/docs/src/API/symmetry.md b/docs/src/API/symmetry.md index ea221ed6..03f2a47b 100644 --- a/docs/src/API/symmetry.md +++ b/docs/src/API/symmetry.md @@ -120,6 +120,7 @@ iscompatible ## PointSymmetryDatabase ```@docs +PointSymmetryDatabase PointSymmetryDatabase.get2d PointSymmetryDatabase.get3d PointSymmetryDatabase.find2d @@ -127,6 +128,11 @@ PointSymmetryDatabase.find3d ``` +## IrrepDatabase + +```@docs +IrrepDatabase +``` ## Symmorphic Symmetry diff --git a/docs/src/Symmetry/irrep.md b/docs/src/Symmetry/irrep.md index 4af1261e..a2f794e3 100644 --- a/docs/src/Symmetry/irrep.md +++ b/docs/src/Symmetry/irrep.md @@ -1,5 +1,39 @@ # Irreducible Representations +Given a symmetry of a system, its Hamiltonian can be broken into sectors corresponding to the irreducible representations, or *irreps*, of the symmetry group. +(See [Using Symmetry in Exact Diagonalization](http://kyungminlee.org/symmetry-for-numerics).) + + +## IrrepComponent + +A symmetry group in general has multiple irreps, and some of those irreps may be of dimension higher than one. +The data structure that represents the component of an irrep of a symmetry is [`IrrepComponent`](@ref), which has three fields: +`symmetry`, the underlying symmetry, `irrep_index`, the irrep it refers to, and `irrep_component`, the component in a multidimensional irrep. + + +## Irreps of Translation Symmetry + +Translation symmetry forms an Abelian group. +All irreps of a translation symmetry are, therefore, one-dimensional, corresponding to *Fourier modes*, or *momentum sectors*. +Given a Bravais lattice, together with its generating translations, irreps can be computed simply as ```math -\Gamma_i -``` \ No newline at end of file +\Phi_{\mathbf{k}} = \exp \left( - 2 \pi i \sum_{i} k_{i} x_{i} / L_{i} \right) +``` +where $k_{i} \in \{0, 1, \ldots, L_{i}-1 \}$ labels the irrep, +$x_{i}$ labels the translation operations in units of the generators, +and $L_{i}$ is the order (i.e. period length) of the *i*th generator. + +Also since all irreps are one-dimensional, `IrrepComponent` of translation symmetry must, therefore, always have `irrep_component=1`. + + +## Irreps of Point Symmetry + +Point symmetry, on the other hand, is not always Abelian. +Unlike with translation symmetry which is abelian, **LatticeTools.jl** does not compute the irreps of the point group. +Instead, it keeps a database of the point symmetries in two and three dimensions, and their irreps in [`PointSymmetryDatabase`](@ref). +(* This may later be replaced by [`IrrepDatabase`](@ref).) +The representation of the point operation, and their irreps are taken from the [Bilbao Crystallographic Server](https://www.cryst.ehu.es). + + +[Group representation](https://en.wikipedia.org/wiki/Group_representation) +[Irreducible representation](https://en.wikipedia.org/wiki/Irreducible_representation) diff --git a/docs/src/Symmetry/space-operation.md b/docs/src/Symmetry/space-operation.md index 922e32dc..47f8ab01 100644 --- a/docs/src/Symmetry/space-operation.md +++ b/docs/src/Symmetry/space-operation.md @@ -8,6 +8,7 @@ Here `S` is the type for the coordinates. using LatticeTools ``` + ## Translation Operation The type [`TranslationOperation{S}`](@ref) represents translation operation @@ -30,6 +31,7 @@ t([3, 4]) apply_operation(t, [5, 6]) ``` + ## Point Operation Point operation is represented by the type [`PointOperation{S}`](@ref), @@ -52,6 +54,7 @@ p = PointOperation([0 1; 1 0]) p([2, 5]) ``` + ## Space Operation ```@repl tbl diff --git a/docs/src/Symmetry/space-symmetry-database.md b/docs/src/Symmetry/space-symmetry-database.md new file mode 100644 index 00000000..bdadd06d --- /dev/null +++ b/docs/src/Symmetry/space-symmetry-database.md @@ -0,0 +1,5 @@ +# Space Symmetry Database + +[`PointSymmetryDatabase`](@ref) + +[`IrrepDatabase`](@ref) \ No newline at end of file diff --git a/docs/src/Symmetry/space-symmetry.md b/docs/src/Symmetry/space-symmetry.md index f1f28413..fd4bd09b 100644 --- a/docs/src/Symmetry/space-symmetry.md +++ b/docs/src/Symmetry/space-symmetry.md @@ -7,7 +7,7 @@ ## Group Space symmetry operations (translation, rotation, inversion, mirror, etc.) form a mathematical structure called [*group*](https://en.wikipedia.org/wiki/Group). -Within **LatticeTools.jl**, ther term **group** refers to the mathematical group structure of a symmetry, which essentially boils down to its multiplication table. +Within **LatticeTools.jl**, the term **group** refers to the mathematical group structure of a symmetry, which essentially boils down to its multiplication table. Currently, the only type which implements a group is [`FiniteGroup`](@ref). The elements of a [`FiniteGroup`](@ref) are consecutive integers from 1 to n: @@ -16,6 +16,7 @@ The following example produces the [Klein four-group](https://en.wikipedia.org/w ```@setup group using LatticeTools +g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]) ``` ```@repl group @@ -24,12 +25,7 @@ g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]) Group binary operation can be applied by [`group_product`](@ref) -```@setup product -using LatticeTools -g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]) -``` - -```@repl product +```@repl group group_product(g, 3, 4) p = group_product(g); p(3, 4) @@ -38,12 +34,7 @@ p(3, 4) Given a group, a subgroup which contains certain elements can be generated by [`generate_subgroup`](@ref). The function returns the set of elements, not the group structure, of the subgroup including all of the specified elements, along with elements that are generated by the group law. -```@setup subgroup -using LatticeTools -g = FiniteGroup([1 2 3 4; 2 1 4 3; 3 4 1 2; 4 3 2 1]) -``` - -```@repl subgroup +```@repl group generate_subgroup(g, 3) generate_subgroup(g, [1, 3]) generate_subgroup(g, [2, 3]) @@ -51,11 +42,7 @@ generate_subgroup(g, [2, 3]) A group multiplication table of arbitrary objects with an arbitrary operation can be produced using [`group_multiplication_table`](@ref): -```@setup multiplication-table -using LatticeTools # hide -``` - -```@repl multiplication-table +```@repl group group_multiplication_table([[1 0; 0 1], [1 0; 0 -1], [-1 0; 0 1], [-1 0; 0 -1]]) ``` @@ -65,7 +52,7 @@ group_multiplication_table([[1 0; 0 1], [1 0; 0 -1], [-1 0; 0 1], [-1 0; 0 -1]]) The term **symmetry**, on the other hand, is used to refer to realizations of the group structures on the lattice. Examples are [`TranslationSymmetry`](@ref), [`PointSymmetry`](@ref). -In the current implementation of `LatticeTools.jl`, a symmetry object contains the following fields: +In the current implementation of **LatticeTools.jl**, a symmetry object contains the following fields: - group - generators - conjugacy classes @@ -106,7 +93,7 @@ A symmorphic space symmetry is thus a semidirect product of translation symmetry ``` where *S*, *T*, and *P* are space symmetry, translation symmetry, and point symmetry about a point *O*. -In the current implementation of `LatticeTools.jl`, the point *O* is always assumed to be the origin. +In the current implementation of **LatticeTools.jl**, the point *O* is always assumed to be the origin. For proper specification of the space group, the sites need to be located at the correct positions. @@ -114,28 +101,26 @@ For proper specification of the space group, the sites need to be located at the The elements of the space symmetry (without considering combination with some local unitary transformation) can be thought of as a subset of the permutation group of the lattice sites. -An "embedding" of a symmetry onto a lattice, is a symmetry structure whose elements are permutations of sites represented by [`SitePermutation`](@ref). +An **embedding** of a symmetry onto a lattice, is a symmetry structure whose elements are permutations of sites represented by [`SitePermutation`](@ref). ### Symmetry embedding of symmorphic symmetry The semi-direct product and the embedding commutes. -See the following commutative diagram: ``` - T ⋊ P → E(L,P) + (T, P) ↦ T ⋊ P - ↓ ↘ ↓ + ↧ ↧ - E(L,T) → E(L, T ⋊ P) + (E(L,T), E(L,P)) ↦ E(L, T ⋊ P) ``` -where E(L, S) is embedding of *abstract* space group S onto lattice L. +*E(L, S)* is embedding of *abstract* space group *S* onto lattice *L*. ## Compatibility between symmetries, symmetry-embeddings, and their irrep components -In case of (symmorphic) space symmetry, we want to make sure that the translation symmetry and the point symmetry are "compatible". - -The compatibility condition is the following - +In case of (symmorphic) space symmetry, we need to make sure that the translation symmetry and the point symmetry are "compatible". +In other words, the symmetry that we impose must be allowed by the underlying lattice. +Let's consider compatibilities between lattices and symmetries. ### 1. Between lattice and translation symmetry @@ -145,35 +130,15 @@ encodes directly the information of the translation symmetry, a [`Lattice`](@ref) and a [`TranslationSymmetry`](@ref) is compatible if they *share the same Bravais lattice*. No further requirement is needed. - ### 2. Between lattice and point symmetry In order for a point symmetry to be a good symmetry of the lattice, -we need the Bravais lattice to be invariant under the point symmetry at least. -In an infinite lattice, this is always the case, and no requires no checks. -For finite size lattice, however, the situation is different: -Since the finite size lattice with periodic boundary condition can be -understood as an infinite lattice modulo supercell, -the Bravais lattice of the *supercell* also needs to be invariant under -all operations of the point symmetry. The requirement therefore is that -the column vectors of the shape matrix after point operation remain -integer multiples of themselves. - - -### 3. Between translation symmetry and point symmetry - -Same as 2. - - -### 4. Between lattice and translation symmetry embedding - -Translation symmetry embedding is +we need the Bravais lattice to be invariant under the point symmetry at least: +whether this is the case or not depends on the lattice vectors, included in the `UnitCell`. -| a | TS | PS | L | TSE | PSE | -| :-: | :---------------: | :----: | :----: | :----: | :----: | -| TS | same matrix | shape matrix invariant under point operation | same shape matrix | | | -| PS | | | | | | -| L | | | | | | -| TSE | | | | | | -| PSE | | | | | | +The current implementation of **LatticeTools.jl**, however, represent the point group operations in integer coordinates in units of lattice vectors. +This makes a point symmetry always be always compatible with an infinite lattice of the right dimension. +For finite size lattices, however, the situation is different. +Since a finite size lattice with periodic boundary condition can be understood as an infinite lattice modulo supercell, the Bravais lattice of the *supercell* also needs to be invariant under all operations of the point symmetry. +The requirement therefore is that the column vectors of the shape matrix after point operation remain integer multiples of themselves. diff --git a/docs/src/index.md b/docs/src/index.md index aa1f3f12..979ddf61 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,6 +1,8 @@ # Welcome to LatticeTools.jl + ## Overview + **LatticeTools.jl** is a Julia package for defining lattices and performing space symmetry analysis on them, useful for creating and solving quantum Hamiltonians. ## Features @@ -9,6 +11,7 @@ - **Momentum space**: Provides methods for transformations between real space and momentum space. - **Symmetry analysis**: Supports group representation theoretical analysis on translation and point symmetry. Currently, only symmorphic space groups are supported. + ## Installation `LatticeTools` is currently not included in Julia's default package registry. @@ -18,6 +21,7 @@ To install, add the package registry `KyugminLeeRegistry` and then install the p (@v1.5) pkg> add LatticeTools ``` + ## Quick Example ```@example example-unitcell diff --git a/examples/example_group_isomorphism.jl b/examples/example_group_isomorphism.jl index 4ad3e132..469d501a 100644 --- a/examples/example_group_isomorphism.jl +++ b/examples/example_group_isomorphism.jl @@ -6,10 +6,10 @@ using LatticeTools using Formatting function display_matrix(io::IO, matrix::AbstractMatrix; prefix::AbstractString="") - width = ceil(Int, maximum(length("$item") for item in matrix)/4)*4 + width = ceil(Int, maximum(length("$item")+1 for item in matrix)/4)*4 for row in eachrow(matrix) for (icol, col) in enumerate(row) - print(io, icol == 1 ? prefix : " ") + icol == 1 && print(io, prefix) printfmt(io, "{:>$(width)s}", "$col") end println(io) diff --git a/examples/example_little_group_2d.jl b/examples/example_little_group_2d.jl index a800003d..6f52e051 100644 --- a/examples/example_little_group_2d.jl +++ b/examples/example_little_group_2d.jl @@ -6,15 +6,11 @@ using Formatting using Plots function display_matrix(io::IO, matrix::AbstractMatrix; prefix::AbstractString="") - width = ceil(Int, maximum(length("$item") for item in matrix)/4)*4 + width = ceil(Int, maximum(length("$item")+1 for item in matrix)/4)*4 for row in eachrow(matrix) for (icol, col) in enumerate(row) - if icol == 1 - print(io, prefix) - printfmt(io, "{:>$(width)s}", "$col") - else - printfmt(io, " {:>$(width)s}", "$col") - end + icol == 1 && print(io, prefix) + printfmt(io, "{:>$(width)s}", "$col") end println(io) end diff --git a/examples/example_point_group_4mm.jl b/examples/example_point_group_4mm.jl index 821a5ec6..e8516551 100644 --- a/examples/example_point_group_4mm.jl +++ b/examples/example_point_group_4mm.jl @@ -5,15 +5,11 @@ using LatticeTools using Formatting: printfmt function display_matrix(io::IO, matrix::AbstractMatrix; prefix::AbstractString="") - width = ceil(Int, maximum(length("$item") for item in matrix)/4)*4 + width = ceil(Int, maximum(length("$item")+1 for item in matrix)/4)*4 for row in eachrow(matrix) for (icol, col) in enumerate(row) - if icol == 1 - print(io, prefix) - printfmt(io, "{:>$(width)s}", "$col") - else - printfmt(io, " {:>$(width)s}", "$col") - end + icol == 1 && print(io, prefix) + printfmt(io, "{:>$(width)s}", "$col") end println(io) end diff --git a/src/Irrep/irrepdatabase.jl b/src/Irrep/irrepdatabase.jl index 7cd03489..82d55e33 100644 --- a/src/Irrep/irrepdatabase.jl +++ b/src/Irrep/irrepdatabase.jl @@ -1,3 +1,7 @@ +""" +Irrep datbase module. +Provides irreducible representation data of point symmetries in three dimensions (and therefore two and one). +""" module IrrepDatabase import Pkg From 922d53f712ec5add81d35a6d4c0d7a40d6ce7fab Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Mon, 31 Aug 2020 12:13:57 -0400 Subject: [PATCH 08/13] Update documentation --- docs/src/API/symmetry.md | 12 ++++++------ docs/src/lattice.md | 9 ++------- src/Symmetry/pointsymmetrydatabase.jl | 8 +++++++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/src/API/symmetry.md b/docs/src/API/symmetry.md index 03f2a47b..94700963 100644 --- a/docs/src/API/symmetry.md +++ b/docs/src/API/symmetry.md @@ -120,18 +120,18 @@ iscompatible ## PointSymmetryDatabase ```@docs -PointSymmetryDatabase -PointSymmetryDatabase.get2d -PointSymmetryDatabase.get3d -PointSymmetryDatabase.find2d -PointSymmetryDatabase.find3d +LatticeTools.PointSymmetryDatabase +LatticeTools.PointSymmetryDatabase.get2d +LatticeTools.PointSymmetryDatabase.get3d +LatticeTools.PointSymmetryDatabase.find2d +LatticeTools.PointSymmetryDatabase.find3d ``` ## IrrepDatabase ```@docs -IrrepDatabase +LatticeTools.IrrepDatabase ``` diff --git a/docs/src/lattice.md b/docs/src/lattice.md index 454e361c..e6041d17 100644 --- a/docs/src/lattice.md +++ b/docs/src/lattice.md @@ -37,8 +37,7 @@ In such a case, the equivalence relation within the basis under translation is i [`Hypercube`](@ref) provides methods for calculating equivalence relation. For example, when the super cell is defined by lattice vectors `[3, -1]` and `[1, 3]` (in units of the lattice vectors of the original unit cell), -```@repl -using LatticeTools # hide +```@repl example-unitcell cube = Hypercube([3 1; -1 3]) cube.wrap([4, 0]) ``` @@ -50,10 +49,6 @@ Here `cube.wrap` is similar to `divrem`: Now the two can be combined into a [`Lattice`](@ref) using [`makelattice`](@ref). -```@repl -using LatticeTools # hide -unitcell = makeunitcell([1.0 0.0; 0.0 1.0]; SiteType=String) # hide -addsite!(unitcell, "A", FractCoord([0,0], [0.1, 0.0])) # hide -addsite!(unitcell, "B", FractCoord([0,0], [0.0, 0.1])) # hide +```@repl example-unitcell lattice = makelattice(unitcell, [3 1; -1 3]) ``` \ No newline at end of file diff --git a/src/Symmetry/pointsymmetrydatabase.jl b/src/Symmetry/pointsymmetrydatabase.jl index 835b7c89..be6050da 100644 --- a/src/Symmetry/pointsymmetrydatabase.jl +++ b/src/Symmetry/pointsymmetrydatabase.jl @@ -1,3 +1,8 @@ +""" +Point symmetry database module. +Provides matrix representations (in units of lattice vectors) and other information about the point symmetries +(Hermann-Mauguin notation, names of the elements, etc.), together with character tables and irreducible representations. +""" module PointSymmetryDatabase import Serialization @@ -19,7 +24,7 @@ NUM_POINT_SYMMETRIES_3D = 32 POINT_SYMMETRY_DATABASE_3D = Vector{PointSymmetry}(undef, NUM_POINT_SYMMETRIES_3D) POINT_SYMMETRY_LOOKUP_3D = Dict{Vector{String}, Int}() - +# COV_EXCL_START function load_yaml() for group_index in 1:NUM_POINT_SYMMETRIES_2D psym = load_group_2d(group_index) @@ -91,6 +96,7 @@ function load_group_3d(group_index::Integer) point_symmetry = read_point_symmetry(data_yaml) return point_symmetry end +# COV_EXCL_STOP # 3D by default From d25efc1f321a8754cc4612d47e2ce11c4dc3b414 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Mon, 31 Aug 2020 12:30:52 -0400 Subject: [PATCH 09/13] Add space-symmetry-database.md to make.jl --- docs/make.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/make.jl b/docs/make.jl index 5cf3fff8..c653a600 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -33,6 +33,7 @@ makedocs( "Symmetry/space-symmetry.md", "Symmetry/space-operation.md", "Symmetry/irrep.md", + "Symmetry/space-symmetry-database.md", ], "Examples" => [ "Group Isomorphism" => "generated/example_group_isomorphism.md", From 95aca9474d6ab6b7d42bb2baa79aad7938d7c047 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Mon, 31 Aug 2020 12:41:14 -0400 Subject: [PATCH 10/13] Update logo --- docs/src/assets/logo.png | Bin 22716 -> 24466 bytes logo/lattice-3.json | 36 ++++++++++++++++++++++++++ logo/{lattice.json => lattice-5.json} | 0 logo/make.jl | 10 +++---- 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 logo/lattice-3.json rename logo/{lattice.json => lattice-5.json} (100%) diff --git a/docs/src/assets/logo.png b/docs/src/assets/logo.png index 352d1351b82e1d7dcff7cfcee2cc393ec1db211f..fc1a16f4bab460a6e341e184220d3df73cefebab 100644 GIT binary patch literal 24466 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

%`DK}$hXP5pfJr)Gc60>R~ZZgt= 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 z%0D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 JDp4>G`9I&rUwZ%m literal 22716 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 Q4FLe5sG;yl-u(Ih0nh0_wg3PC diff --git a/logo/lattice-3.json b/logo/lattice-3.json new file mode 100644 index 00000000..288c3340 --- /dev/null +++ b/logo/lattice-3.json @@ -0,0 +1,36 @@ +{ + "sites": [ + ["A", [0, 0]], + ["B", [0, 0]], + ["C", [0, 0]], + + ["A", [1, 0]], + ["B", [1, 0]], + ["C", [1, 0]], + + ["A", [0, 1]], + ["B", [0, 1]], + ["C", [0, 1]], + + ["A", [1, 1]], + ["B", [1, 1]], + ["C", [1, 1]], + + ["A", [2, 1]], + ["B", [2, 1]], + ["C", [2, 1]], + + ["A", [1, 2]], + ["B", [1, 2]], + ["C", [1, 2]], + + ["A", [2, 2]], + ["B", [2, 2]], + ["C", [2, 2]], + + ["A", [2, 3]], + ["B", [2, 0]], + ["C", [-1, 0]] + ] + +} \ No newline at end of file diff --git a/logo/lattice.json b/logo/lattice-5.json similarity index 100% rename from logo/lattice.json rename to logo/lattice-5.json diff --git a/logo/make.jl b/logo/make.jl index 5dfd2a45..0d481d2d 100644 --- a/logo/make.jl +++ b/logo/make.jl @@ -4,7 +4,7 @@ using LatticeTools include("Kagome.jl") -lattice_data = JSON.parsefile("lattice.json") +lattice_data = JSON.parsefile("lattice-3.json") sites = [(sitetype, [R...]) for (sitetype, R) in lattice_data["sites"]] kagome = Kagome.make_kagome_obc(sites) site_coordinates = [] @@ -17,12 +17,12 @@ end site_coordinates = hcat(site_coordinates...) site_coordinates[2,:] = -site_coordinates[2,:] -Drawing(840, 300, "logo.svg") +Drawing(800, 300, "logo.png") origin() -translate(-460, 110) +translate(-450, 130) -let ratio = 88, radius = 10, radius_large = 14, offset = (0,0), +let ratio = 100, radius = 13, radius_large = 18, offset = (0,0), sitecolor = Dict("A" => "brown3", "B" => "forestgreen", "C" => "mediumorchid3") sethue("gray") @@ -44,7 +44,7 @@ let ratio = 88, radius = 10, radius_large = 14, offset = (0,0), end end -translate(400, -136) +translate(360, -160) sethue("black") fontsize(144) fontface("Tamil MN") From 612b01cccc4e64fe0a092bfb685d2a7f39426125 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Tue, 8 Sep 2020 09:18:39 -0400 Subject: [PATCH 11/13] Update README.md Project description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ef20f57..159428dd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ |:-----------------:|:----------------:|:-----------------:| | [![**STABLE**][docs-stable-img]][docs-stable-url] [![**DEV**][docs-dev-img]][docs-dev-url] | [![Build Status][travis-img]][travis-url] [![Build Status][appveyor-img]][appveyor-url] | [![Code Coverage][codecov-img]][codecov-url] [![Code Coverage][coveralls-img]][coveralls-url] | -[LatticeTools.jl](https://github.com/kyungminlee/LatticeTools.jl) is a Julia package which provides functionalities to define lattices and perform symmetry analysis, with focus on interacting many-body quantum Hamiltonians. +[LatticeTools.jl](https://github.com/kyungminlee/LatticeTools.jl) is a Julia package that provides functionalities to define lattices and perform symmetry analyses useful for studying interacting quantum many-body Hamiltonians. ## Installation From a688af48ded46cb55445c44e06b540daafdaff3b Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Tue, 8 Sep 2020 17:12:25 -0400 Subject: [PATCH 12/13] Split parseexpr and cleanupnumber into MathExpr --- Project.toml | 5 +- src/Basic/basic.jl | 171 ------------------------ src/Basic/hypercube.jl | 13 +- src/Irrep/irrepdatabase.jl | 7 +- src/LatticeTools.jl | 1 - src/Symmetry/compatibility.jl | 7 +- src/Symmetry/pointsymmetry.jl | 7 +- src/Symmetry/translationsymmetry.jl | 12 +- src/SymmetryOperation/pointoperation.jl | 6 +- src/SymmetryOperation/spaceoperation.jl | 11 +- test/runtests.jl | 2 - test/test_basic.jl | 146 -------------------- test/test_parser.jl | 47 ------- 13 files changed, 39 insertions(+), 396 deletions(-) delete mode 100644 src/Basic/basic.jl delete mode 100644 test/test_basic.jl delete mode 100644 test/test_parser.jl diff --git a/Project.toml b/Project.toml index e56b276c..6506f0ef 100644 --- a/Project.toml +++ b/Project.toml @@ -4,12 +4,13 @@ author = "Kyungmin Lee" version = "0.7.1" [deps] -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" -YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +MathExpr = "7e419fb4-4148-4024-80a8-2502d26d6b11" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" [compat] julia = ">= 1.5" diff --git a/src/Basic/basic.jl b/src/Basic/basic.jl deleted file mode 100644 index a8ca35cf..00000000 --- a/src/Basic/basic.jl +++ /dev/null @@ -1,171 +0,0 @@ -export ExactLinearAlgebra - -module ExactLinearAlgebra - import LinearAlgebra - - ScalarType = Union{Integer, Complex{<:Integer}, <:Rational, Complex{<:Rational}} - - function get_cofactor_matrix_unsafe!( - out::AbstractMatrix{I1}, - mat::AbstractMatrix{I2}, - row::Integer, - col::Integer, - ) where {I1<:ScalarType, I2<:ScalarType} - out[1:row-1, 1:col-1] = mat[1:row-1, 1:col-1] - out[1:row-1, col:end] = mat[1:row-1, col+1:end] - out[row:end, 1:col-1] = mat[row+1:end, 1:col-1] - out[row:end, col:end] = mat[row+1:end, col+1:end] - return out - end - - function determinant_unsafe(mat::AbstractMatrix{S}) where {S<:ScalarType} - n = size(mat)[1] - n == 1 && return mat[1] - out = Matrix{S}(undef, (n-1, n-1)) - sign = 1 - D = zero(S) - for f = 1:n - get_cofactor_matrix_unsafe!(out, mat, 1, f) - @inbounds D += sign * mat[1,f] * determinant_unsafe(out) - sign = -sign - end - return D - end - - function determinant(mat::AbstractMatrix{S}) where {S<:ScalarType} - n, m = size(mat) - n != m && throw(ArgumentError("matrix needs to be square")) - n <= 0 && throw(ArgumentError("matrix empty")) - return determinant_unsafe(mat) - end - - determinant(mat::AbstractMatrix{<:AbstractFloat}) = LinearAlgebra.det(mat) - - function inverse(mat::AbstractMatrix{S}) where {S<:ScalarType} - n, m = size(mat) - n != m && throw(ArgumentError("matrix needs to be square")) - n <= 0 && throw(ArgumentError("matrix empty")) - n == 1 && return ones(S, (1,1)) .// mat[1] - cofactor = Array{S}(undef, (n, n)) - temp = Array{S}(undef, (n-1, n-1)) - for r in 1:n, c in 1:n - sign = 1 - 2 * mod(r+c, 2) - get_cofactor_matrix_unsafe!(temp, mat, r, c) - @inbounds cofactor[r,c] = sign * determinant_unsafe(temp) - end - D = sum(mat[1,:] .* cofactor[1,:]) - return transpose(cofactor) // D - end - - inverse(mat::AbstractMatrix{<:AbstractFloat}) = LinearAlgebra.inv(mat) - -end # module ExactLinearAlgebra - - -module ExprParser - -export parse_expr - -SYMBOL_DATABASE = Dict( - :i => im, - :im => im, - :pi => pi, - :π => π, - :+ => (+), :- => (-), :* => (*), :/ => (/), :\ => (\), :^ => (^), :// => (//), - :cos => cos, :sin => sin, :tan => tan, - :exp => exp, :cis => cis, - :cospi => cospi, :sinpi => sinpi, - :sqrt => sqrt, - :log => log, - :abs => abs, :abs2 => abs2, :sign => sign, - :conj => conj, :real => real, :imag => imag, - :angle => angle -) - -myeval(expr::Number) = expr -function myeval(expr::Symbol) - if haskey(SYMBOL_DATABASE, expr) - return SYMBOL_DATABASE[expr] - else - error("unsupported symbol $expr") - end -end - -function myeval(expr::Expr) - if expr.head == :call - ftn, args = Iterators.peel(myeval.(expr.args)) - return ftn(args...) - elseif expr.head == :vect - return [(myeval.(expr.args))...] - elseif expr.head == :tuple - return tuple((myeval.(expr.args))...) - elseif expr.head == :hcat - return hcat((myeval.(expr.args))...) - elseif expr.head == :row - return hcat((myeval.(expr.args))...) - elseif expr.head == :vcat - return vcat((myeval.(expr.args))...) - else - error("unsupported expression $expr") - end -end - -parse_expr(expr::Number) = expr -parse_expr(expr::AbstractString) = myeval(Meta.parse(expr)) -parse_expr(expr::AbstractArray) = [parse_expr(elem) for elem in expr] - -end - - -using .ExprParser: parse_expr - -#= # commented for now -function parse_table(s::AbstractString) - s = strip(s) - rows = Vector{Int}[] - for line in split(s, "\n") - line = strip(line) - row = [parse(Int, x) for x in split(line)] - !isempty(row) && push!(rows, row) - end - return transpose(hcat(rows...)) -end -=# - - -function cleanup_number(x::AbstractFloat, tol::Real) - units = [16, 16/sqrt(3), 16*sqrt(3)] - for unit in units - if isapprox(x*unit, round(x*unit); atol=tol) - return round(x*unit)/unit - end - end - return x -end - -cleanup_number(x::Integer, tol::Real) = x -cleanup_number(x::Rational{<:Integer}, tol::Real) = x - -function cleanup_number(x::Complex, tol::Real) - return cleanup_number(real(x), tol) + im * cleanup_number(imag(x), tol) -end - -cleanup_number(x::AbstractArray, tol::Real) = [cleanup_number(y, tol) for y in x] - - -function extended_gcd(a::Integer, b::Integer) - sign_a, sign_b = sign(a), sign(b) - s, old_s = 0, 1 - r, old_r = abs(b), abs(a) - while r != 0 - quotient = old_r ÷ r - (old_r, r) = (r, old_r - quotient * r) - (old_s, s) = (s, old_s - quotient * s) - end - if b != 0 - bezout_t = (old_r - old_s * abs(a)) ÷ abs(b) - else - bezout_t = 0 - end - return (old_r, [sign_a * old_s, sign_b * bezout_t]) -end diff --git a/src/Basic/hypercube.jl b/src/Basic/hypercube.jl index 870e7b0e..c151a4bd 100644 --- a/src/Basic/hypercube.jl +++ b/src/Basic/hypercube.jl @@ -4,6 +4,7 @@ export generate_coordinates export volume export isequiv +import MathExpr """ Hypercube(shape) @@ -27,10 +28,10 @@ struct Hypercube msg = "scale_matrix is not square: dimensions are ($dim, $dim2)" throw(DimensionMismatch(msg)) end - det = ExactLinearAlgebra.determinant(shape_matrix) + det = MathExpr.determinant(shape_matrix) det == 0 && throw(ArgumentError("scale matrix null")) - inverse_shape_matrix = ExactLinearAlgebra.inverse(shape_matrix) + inverse_shape_matrix = MathExpr.inverse(shape_matrix) function wrap(r::AbstractArray{<:Integer}, mode::RoundingMode=RoundDown) rnd = (x) -> round(Int, x, mode) R = rnd.(inverse_shape_matrix * r) @@ -53,7 +54,7 @@ dimension(cube::Hypercube) = size(cube.shape_matrix, 1) Return the signed volume of the hypercube, defined by the determinant of the shape. """ -volume(cube::Hypercube) = ExactLinearAlgebra.determinant(cube.shape_matrix) +volume(cube::Hypercube) = MathExpr.determinant(cube.shape_matrix) function Base.:(==)(lhs::Hypercube, rhs::Hypercube) @@ -68,7 +69,7 @@ Check whether the two hypercubes are equivalent. """ function isequiv(lhs::Hypercube, rhs::Hypercube) R, r = lhs.wrap(rhs.shape_matrix) - if abs(ExactLinearAlgebra.determinant(R)) != 1 || !iszero(r) + if abs(MathExpr.determinant(R)) != 1 || !iszero(r) return false end return true @@ -125,7 +126,7 @@ function find_generators_2d(cube::Hypercube) axis1 = make_loop(r1) mod(cubevolume, length(axis1)) != 0 && continue for r2 in allowed_pairs - ExactLinearAlgebra.determinant(hcat(r1, r2)) != 1 && continue + MathExpr.determinant(hcat(r1, r2)) != 1 && continue axis2 = make_loop(r2) cubevolume != length(axis1) * length(axis2) && continue coordinates = vec([cube.wrap(sum(x))[2] @@ -153,7 +154,7 @@ function generate_coordinates( let dim = dimension(cube) if size(generator_translations) != (dim, dim) throw(DimensionMismatch("Hypercube and generator_translations have different dimensions")) - elseif abs(ExactLinearAlgebra.determinant(generator_translations)) != 1 + elseif abs(MathExpr.determinant(generator_translations)) != 1 throw(ArgumentError("generator_translations is not unimodular")) end end diff --git a/src/Irrep/irrepdatabase.jl b/src/Irrep/irrepdatabase.jl index 82d55e33..f11aa81b 100644 --- a/src/Irrep/irrepdatabase.jl +++ b/src/Irrep/irrepdatabase.jl @@ -9,9 +9,10 @@ import Serialization using LinearAlgebra import YAML +import MathExpr using ..LatticeTools: FiniteGroup, IrrepData -using ..LatticeTools: cleanup_number, parse_expr, group_isomorphism, group_multiplication_table, simplify_name +using ..LatticeTools: group_isomorphism, group_multiplication_table, simplify_name IRREP_DATABASE = IrrepData[] @@ -31,14 +32,14 @@ function load_yaml() error("Conjugacy class not canonical") # COV_EXCL_LINE end - character_table = cleanup_number(transpose(hcat(parse_expr(data["CharacterTable"])...)), tol) + character_table = MathExpr.cleanupnumber(transpose(hcat(MathExpr.parseexpr(data["CharacterTable"])...)), tol) let nc = length(conjugacy_classes) size(character_table) != (nc, nc) && error("character table has wrong size") end irreps = Vector{Matrix{ComplexF64}}[] for item in data["IrreducibleRepresentations"] - matrices = Matrix{ComplexF64}[cleanup_number(transpose(hcat(parse_expr(elem)...)), tol) for elem in item] + matrices = Matrix{ComplexF64}[MathExpr.cleanupnumber(transpose(hcat(MathExpr.parseexpr(elem)...)), tol) for elem in item] push!(irreps, matrices) end push!(IRREP_DATABASE, IrrepData(group, conjugacy_classes, character_table, irreps)) diff --git a/src/LatticeTools.jl b/src/LatticeTools.jl index 0011cb14..fec1459e 100644 --- a/src/LatticeTools.jl +++ b/src/LatticeTools.jl @@ -1,6 +1,5 @@ module LatticeTools -include("Basic/basic.jl") include("Basic/coord.jl") include("Basic/hypercube.jl") # replacement for hypercube include("Basic/unitcell.jl") diff --git a/src/Symmetry/compatibility.jl b/src/Symmetry/compatibility.jl index f43f535e..3d8255c7 100644 --- a/src/Symmetry/compatibility.jl +++ b/src/Symmetry/compatibility.jl @@ -1,5 +1,6 @@ export iscompatible +import MathExpr ## 1. Hypercube and Operation @@ -18,7 +19,7 @@ end """ function iscompatible(hypercube::Hypercube, op::PointOperation{<:Integer})::Bool R, r = hypercube.wrap(op.matrix * hypercube.shape_matrix) - return iszero(r) && abs(ExactLinearAlgebra.determinant(R)) == 1 + return iszero(r) && abs(MathExpr.determinant(R)) == 1 end @@ -29,7 +30,7 @@ end """ function iscompatible(hypercube::Hypercube, tsym::TranslationSymmetry)::Bool R, r = hypercube.wrap(tsym.hypercube.shape_matrix) - return iszero(r) && abs(ExactLinearAlgebra.determinant(R)) == 1 + return iszero(r) && abs(MathExpr.determinant(R)) == 1 end """ @@ -75,7 +76,7 @@ function iscompatible( pop::PointOperation{<:Integer}, )::Bool !iscompatible(tsym, pop) && return false - reciprocal_matrix = ExactLinearAlgebra.inverse(transpose(pop.matrix)) + reciprocal_matrix = MathExpr.inverse(transpose(pop.matrix)) k1 = tsym.fractional_momenta[tsym_irrep_index] k2 = (x -> mod(x, 1)).(reciprocal_matrix * k1) return k1 == k2 diff --git a/src/Symmetry/pointsymmetry.jl b/src/Symmetry/pointsymmetry.jl index f815d662..23e4c3b2 100644 --- a/src/Symmetry/pointsymmetry.jl +++ b/src/Symmetry/pointsymmetry.jl @@ -20,6 +20,7 @@ export read_point_symmetry export symmetry_name import LinearAlgebra +import MathExpr simplify_name(name::AbstractString) = replace(replace(name, r".*?"=>""), r".*?"=>"") @@ -140,16 +141,16 @@ end """ function read_point_symmetry(data::AbstractDict) tol = Base.rtoldefault(Float64) - read_matrix(obj) = collect(transpose(hcat(parse_expr(obj)...))) + read_matrix(obj) = collect(transpose(hcat(MathExpr.parseexpr(obj)...))) multiplication_table = read_matrix(data["MultiplicationTable"]) group = FiniteGroup(multiplication_table) ord_group = group_order(group) generators = data["Generators"] conjugacy_classes = [item for item in data["ConjugacyClasses"]] - character_table = cleanup_number(read_matrix(data["CharacterTable"]), tol) + character_table = MathExpr.cleanupnumber(read_matrix(data["CharacterTable"]), tol) irreps = [ - Matrix{ComplexF64}[cleanup_number(read_matrix(elem), tol) for elem in item] + Matrix{ComplexF64}[MathExpr.cleanupnumber(read_matrix(elem), tol) for elem in item] for item in data["IrreducibleRepresentations"] ] element_names = data["ElementNames"] diff --git a/src/Symmetry/translationsymmetry.jl b/src/Symmetry/translationsymmetry.jl index 9743a61c..17e4f756 100644 --- a/src/Symmetry/translationsymmetry.jl +++ b/src/Symmetry/translationsymmetry.jl @@ -16,6 +16,8 @@ export symmetry_name export translation_symmetry_embedding +import MathExpr + """ TranslationSymmetry @@ -108,7 +110,7 @@ struct TranslationSymmetry <: AbstractSymmetry{TranslationOperation{Int}} generator_translations::AbstractMatrix{<:Integer}; tol::Real=Base.rtoldefault(Float64), ) - if ExactLinearAlgebra.determinant(generator_translations) != 1 + if MathExpr.determinant(generator_translations) != 1 throw(ArgumentError("generator translation is not unimodular")) end @@ -143,7 +145,7 @@ struct TranslationSymmetry <: AbstractSymmetry{TranslationOperation{Int}} orthogonal_shape_matrix = hcat( [group_order(group, g) * v for (g, v) in zip(generators, eachcol(generator_translations))]...) - orthogonal_reduced_reciprocal_shape_matrix = ExactLinearAlgebra.inverse(transpose(orthogonal_shape_matrix)) + orthogonal_reduced_reciprocal_shape_matrix = MathExpr.inverse(transpose(orthogonal_shape_matrix)) elements = [TranslationOperation(r) for r in coordinates] @@ -161,7 +163,7 @@ struct TranslationSymmetry <: AbstractSymmetry{TranslationOperation{Int}} for kd in orthogonal_coordinates, t in orthogonal_coordinates] - character_table = cleanup_number(character_table, tol) + character_table = MathExpr.cleanupnumber(character_table, tol) let χ = ComplexF64[cis(-2π * LinearAlgebra.dot(k, t)) for k in fractional_momenta, t in coordinates] @@ -651,7 +653,7 @@ end # generator_translations::AbstractMatrix{<:Integer}; # tol::Real=Base.rtoldefault(Float64)) - # if ExactLinearAlgebra.determinant(generator_translations) != 1 + # if MathExpr.determinant(generator_translations) != 1 # throw(ArgumentError("generator translation is not unimodular")) # end @@ -685,7 +687,7 @@ end # [group_order(group, g) * v # for (g, v) in zip(generators, eachcol(generator_translations))]... # ) - # orthogonal_reduced_reciprocal_shape_matrix = ExactLinearAlgebra.inverse(transpose(orthogonal_shape_matrix)) + # orthogonal_reduced_reciprocal_shape_matrix = MathExpr.inverse(transpose(orthogonal_shape_matrix)) # # END Orthogonal # elements = [TranslationOperation(orthogonal_to_coordinate_map[r_ortho]) diff --git a/src/SymmetryOperation/pointoperation.jl b/src/SymmetryOperation/pointoperation.jl index 27a46324..74cef257 100644 --- a/src/SymmetryOperation/pointoperation.jl +++ b/src/SymmetryOperation/pointoperation.jl @@ -4,6 +4,8 @@ export apply_operation export domaintype export isidentity, istranslation, ispoint +import MathExpr + """ PointOperation{S<:Real} @@ -106,13 +108,13 @@ function Base.:(^)(lhs::PointOperation{S}, rhs::Integer) where S if rhs >= 0 return PointOperation(lhs.matrix^rhs) else - lhs_inv_matrix = Matrix{S}(ExactLinearAlgebra.inverse(lhs.matrix)) + lhs_inv_matrix = Matrix{S}(MathExpr.inverse(lhs.matrix)) return PointOperation{S}(lhs_inv_matrix^(-rhs)) end end function Base.inv(lhs::PointOperation{S}) where {S<:Real} - return PointOperation{S}(ExactLinearAlgebra.inverse(lhs.matrix)) + return PointOperation{S}(MathExpr.inverse(lhs.matrix)) end diff --git a/src/SymmetryOperation/spaceoperation.jl b/src/SymmetryOperation/spaceoperation.jl index 7cb15e19..6123f4e7 100644 --- a/src/SymmetryOperation/spaceoperation.jl +++ b/src/SymmetryOperation/spaceoperation.jl @@ -4,6 +4,7 @@ export dimension export isidentity, istranslation, ispoint import LinearAlgebra +import MathExpr """ SpaceOperation{Tp<:Real, Tt<:Real} @@ -229,7 +230,7 @@ function Base.:(*)(lhs::PointOperation{Tp}, rhs::TranslationOperation{Tt}) where end function Base.:(*)(lhs::TranslationOperation{Tt}, rhs::PointOperation{Tp}) where {Tp, Tt} - rhs_matrix_inv = Matrix{Tp}(ExactLinearAlgebra.inverse(rhs.matrix)) + rhs_matrix_inv = Matrix{Tp}(MathExpr.inverse(rhs.matrix)) return SpaceOperation{Tp, Tt}(rhs.matrix, rhs_matrix_inv * lhs.displacement) end @@ -238,7 +239,7 @@ end # = ML MR (x + ρR + inv(MR) ⋅ ρL ) function Base.:(*)(lhs::SpaceOperation{Tp, Tt}, rhs::SpaceOperation{Tp, Tt}) where {Tp, Tt} matrix = lhs.matrix * rhs.matrix - rhs_matrix_inv = Matrix{Tp}(ExactLinearAlgebra.inverse(rhs.matrix)) + rhs_matrix_inv = Matrix{Tp}(MathExpr.inverse(rhs.matrix)) displacement = rhs.displacement + rhs_matrix_inv * lhs.displacement return SpaceOperation{Tp, Tt}(matrix, displacement) end @@ -251,14 +252,14 @@ end function Base.:(*)(lhs::TranslationOperation{Tt}, rhs::SpaceOperation{Tp, Tt}) where {Tp, Tt} matrix = rhs.matrix - rhs_matrix_inv = Matrix{Tp}(ExactLinearAlgebra.inverse(rhs.matrix)) + rhs_matrix_inv = Matrix{Tp}(MathExpr.inverse(rhs.matrix)) displacement = rhs.displacement + rhs_matrix_inv * lhs.displacement return SpaceOperation{Tp, Tt}(matrix, displacement) end function Base.:(*)(lhs::SpaceOperation{Tp, Tt}, rhs::PointOperation{Tp}) where {Tp, Tt} matrix = lhs.matrix * rhs.matrix - rhs_matrix_inv = Matrix{Tp}(ExactLinearAlgebra.inverse(rhs.matrix)) + rhs_matrix_inv = Matrix{Tp}(MathExpr.inverse(rhs.matrix)) displacement = rhs_matrix_inv * lhs.displacement return SpaceOperation{Tp, Tt}(matrix, displacement) end @@ -270,7 +271,7 @@ function Base.:(*)(lhs::PointOperation{Tp}, rhs::SpaceOperation{Tp, Tt}) where { end function Base.inv(arg::SpaceOperation{Tp, Tt}) where {Tp, Tt} - matrix_inv = Matrix{Tp}(ExactLinearAlgebra.inverse(arg.matrix)) + matrix_inv = Matrix{Tp}(MathExpr.inverse(arg.matrix)) return SpaceOperation{Tp, Tt}(matrix_inv, -arg.matrix * arg.displacement) end diff --git a/test/runtests.jl b/test/runtests.jl index 57096ad3..96e00ecb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,6 @@ using Test using LatticeTools -include("test_basic.jl") -include("test_parser.jl") include("test_coord.jl") include("test_unitcell.jl") #include("test_unitcell_deprecated.jl") diff --git a/test/test_basic.jl b/test/test_basic.jl deleted file mode 100644 index c8231b95..00000000 --- a/test/test_basic.jl +++ /dev/null @@ -1,146 +0,0 @@ -using Test -using LatticeTools - -using LinearAlgebra - - -@testset "basic" begin - - @testset "round" begin - for Ti in [Int, Int8, Int16, Int32, Int64] - @test round(Ti, 1//2, RoundDown) == 0 - @test round(Ti, -1//2, RoundDown) == -1 - @test round(Ti, 1//2, RoundUp) == 1 - @test round(Ti, -1//2, RoundUp) == 0 - @test round(Ti, 1//2, RoundToZero) == 0 - @test round(Ti, -1//2, RoundToZero) == 0 - - @test round(Ti, 1//1, RoundDown) == 1 - @test round(Ti, -1//1, RoundDown) == -1 - @test round(Ti, 1//1, RoundUp) == 1 - @test round(Ti, -1//1, RoundUp) == -1 - @test round(Ti, 1//1, RoundToZero) == 1 - @test round(Ti, -1//1, RoundToZero) == -1 - - inf = 1 // 0 - @test_throws DivideError round(Ti, inf, RoundDown) - @test_throws DivideError round(Ti, -inf, RoundDown) - @test_throws DivideError round(Ti, inf, RoundUp) - @test_throws DivideError round(Ti, -inf, RoundUp) - @test_throws DivideError round(Ti, inf, RoundToZero) - @test_throws DivideError round(Ti, -inf, RoundToZero) - end - - for Tf in [Float16, Float32, Float64] - @test round(Tf, 1//2, RoundDown) == 0.0 - @test round(Tf, -1//2, RoundDown) == -1.0 - @test round(Tf, 1//2, RoundUp) == 1.0 - @test round(Tf, -1//2, RoundUp) == 0.0 - @test round(Tf, 1//2, RoundToZero) == 0.0 - @test round(Tf, -1//2, RoundToZero) == 0.0 - - @test round(Tf, 1//1, RoundDown) == 1.0 - @test round(Tf, -1//1, RoundDown) == -1.0 - @test round(Tf, 1//1, RoundUp) == 1.0 - @test round(Tf, -1//1, RoundUp) == -1.0 - @test round(Tf, 1//1, RoundToZero) == 1.0 - @test round(Tf, -1//1, RoundToZero) == -1.0 - - inf = 1 // 0 - @test round(Tf, inf, RoundDown) == Inf - @test round(Tf, -inf, RoundDown) == -Inf - @test round(Tf, inf, RoundUp) == Inf - @test round(Tf, -inf, RoundUp) == -Inf - @test round(Tf, inf, RoundToZero) == Inf - @test round(Tf, -inf, RoundToZero) == -Inf - end - end - - @testset "gcd" begin - using LatticeTools: extended_gcd - let x = 3, y = 0 - r, (a,b) = extended_gcd(x,y) - @test r == 3 - @test a*x + b*y == r - end - let x = 0, y = -3 - r, (a,b) = extended_gcd(x,y) - @test r == 3 - @test a*x + b*y == r - end - - for sx in [-1,1], sy in [-1,1] - let x = 3*sx, y = 4*sy - r, (a,b) = extended_gcd(x,y) - @test r == 1 - @test a*x + b*y == r - end - let x = 6*sx, y = 9*sy - r, (a,b) = extended_gcd(x,y) - @test r == 3 - @test a*x + b*y == r - end - end - end - - @testset "ExactLinearAlgebra" begin - mat = Int[1 2 3; - 4 5 2; - 7 8 10] - - @testset "cofactor" begin - results = Dict( - (1,1) => [5 2; 8 10], - (1,2) => [4 2; 7 10], - (1,3) => [4 5; 7 8], - (2,1) => [2 3; 8 10], - (2,2) => [1 3; 7 10], - (2,3) => [1 2; 7 8], - (3,1) => [2 3; 5 2], - (3,2) => [1 3; 4 2], - (3,3) => [1 2; 4 5] - ) - - for i in 1:3, j in 1:3 - out = ones(Int, (2,2)) - ExactLinearAlgebra.get_cofactor_matrix_unsafe!(out, mat, i, j) - @test out == results[i,j] - end - end - - @testset "determinant" begin - tol = Base.rtoldefault(Float64) - @test_throws ArgumentError ExactLinearAlgebra.determinant([1 2 3; 4 5 6]) - @test_throws ArgumentError ExactLinearAlgebra.determinant(ones(Int, 0,0)) - @test ExactLinearAlgebra.determinant(7*ones(Int, 1, 1)) == 7 - - @test ExactLinearAlgebra.determinant(float.(mat)) == det(mat) - @test abs(det(mat) - ExactLinearAlgebra.determinant(mat)) < tol - for n in [5, 6, 7, 8] - a = rand(-3:3, (n, n)) - det1 = det(a) - det2 = ExactLinearAlgebra.determinant(a) - @test abs(det1 - det2) < Base.rtoldefault(Float64) - end - end # testset determinant - - @testset "inverse" begin - tol = Base.rtoldefault(Float64) - @test_throws ArgumentError ExactLinearAlgebra.inverse([1 2 3; 4 5 6]) - @test_throws ArgumentError ExactLinearAlgebra.inverse(ones(Int, 0, 0)) - @test ExactLinearAlgebra.inverse(7*ones(Int, 1, 1)) == ones(Int, 1, 1)//7 - - @test maximum(abs.(inv(mat) - ExactLinearAlgebra.inverse(float.(mat)))) < tol - @test maximum(abs.(inv(mat) - ExactLinearAlgebra.inverse(mat))) < tol - for n in [5, 6, 7, 8] - a = rand(-3:3, (n, n)) + 30*I - inv1 = inv(a) - inv2 = ExactLinearAlgebra.inverse(a) - @test maximum(abs.(inv1 - inv2)) < tol - end - - end - end # testset ExactLinearAlgebra - - -end diff --git a/test/test_parser.jl b/test/test_parser.jl deleted file mode 100644 index 275ab1ce..00000000 --- a/test/test_parser.jl +++ /dev/null @@ -1,47 +0,0 @@ -using Test -using LatticeTools - -using LatticeTools: parse_expr - - -@testset "parse_expr" begin - @test 1 == parse_expr(1) - @test 1 == parse_expr("1") - @test 1.5 == parse_expr("1.5") - @test 1.5im == parse_expr("1.5im") - @test 1.5im == parse_expr("1.5i") - @test [1,2,3] == parse_expr("[1,2,3]") - @test [1,2,3im] == parse_expr([1, "2", "3i"]) - - @test parse_expr("2") == 2 - @test parse_expr("i") == im - @test parse_expr("cis(2)") == cis(2) - @test parse_expr("exp(2i)") == exp(2im) - @test parse_expr("[10, π, exp(1)]") == [10, π, exp(1)] - @test parse_expr("[10 π]") == [10 π] - @test parse_expr("[1 2; 3 4]") == [1 2; 3 4] - @test parse_expr("(1, 2.0)") == (1, 2.0) - - @test parse_expr("2+3") == 2+3 - @test parse_expr("2-3") == 2-3 - @test parse_expr("2*3") == 2*3 - @test parse_expr("2/3") == 2/3 - @test parse_expr("2//3") == 2//3 - @test parse_expr("2\\3") == 2\3 - @test parse_expr("2^3") == 2^3 - - for unary_ftn in [cos, sin, tan, exp, cis, cospi, sinpi, sqrt, log, abs, abs2, sign, conj, conj, real, imag, angle] - @test parse_expr("$unary_ftn(3.0 + 5.0i)") == unary_ftn(3.0 + 5.0im) - end - @test_throws ErrorException parse_expr("j") - @test_throws ErrorException parse_expr("true ? π : -1") -end - -@testset "cleanup" begin - using LatticeTools: cleanup_number - @test cleanup_number(42, 1E-8) == 42 - @test cleanup_number(1.5 + 1E-12, 1E-8) == 1.5 - @test cleanup_number([1.0 + 1E-12, 2.0 - 1E-12, 3.0], 1E-8) == [1.0, 2.0, 3.0] - @test cleanup_number(0.1234567, 1E-8) == 0.1234567 - @test cleanup_number(-1//3, 1E-8) == -1//3 -end From 5f297999d9db810f270dc6feef5b61f823ae1e18 Mon Sep 17 00:00:00 2001 From: Kyungmin Lee Date: Tue, 8 Sep 2020 17:39:26 -0400 Subject: [PATCH 13/13] Bump up version to 0.8.0 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 6506f0ef..ce7eeabd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "LatticeTools" uuid = "8a267902-5e0e-44c3-8ef8-9b2b5c352816" author = "Kyungmin Lee" -version = "0.7.1" +version = "0.8.0" [deps] FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"