From b7c75b6c4efa38e5a4ec549bd7b6d7d1f9a06cd5 Mon Sep 17 00:00:00 2001 From: pmla Date: Tue, 11 Sep 2018 16:41:44 -0400 Subject: [PATCH 01/13] Added compute for Polyhedral Template Matching --- doc/src/Eqs/ptm_rmsd.jpg | Bin 0 -> 6833 bytes doc/src/Eqs/ptm_rmsd.tex | 21 + doc/src/compute_ptm_atom.txt | 117 ++ src/USER-PTM/LICENSE | 7 + src/USER-PTM/alloy_types.cpp | 101 ++ src/USER-PTM/alloy_types.h | 9 + src/USER-PTM/canonical_coloured.cpp | 167 ++ src/USER-PTM/canonical_coloured.h | 9 + src/USER-PTM/cell.cpp | 1368 ++++++++++++++ src/USER-PTM/cell.h | 324 ++++ src/USER-PTM/compute_ptm_atom.cpp | 307 ++++ src/USER-PTM/compute_ptm_atom.h | 48 + src/USER-PTM/config.h | 129 ++ src/USER-PTM/convex_hull_incremental.cpp | 363 ++++ src/USER-PTM/convex_hull_incremental.h | 27 + src/USER-PTM/deformation_gradient.cpp | 37 + src/USER-PTM/deformation_gradient.h | 142 ++ src/USER-PTM/fundamental_mappings.h | 180 ++ src/USER-PTM/graph_data.cpp | 2059 ++++++++++++++++++++++ src/USER-PTM/graph_data.h | 37 + src/USER-PTM/graph_tools.cpp | 52 + src/USER-PTM/graph_tools.h | 11 + src/USER-PTM/index_ptm.cpp | 218 +++ src/USER-PTM/initialize_data.cpp | 71 + src/USER-PTM/initialize_data.h | 61 + src/USER-PTM/neighbour_ordering.cpp | 203 +++ src/USER-PTM/neighbour_ordering.h | 13 + src/USER-PTM/normalize_vertices.cpp | 55 + src/USER-PTM/normalize_vertices.h | 8 + src/USER-PTM/polar.cpp | 337 ++++ src/USER-PTM/polar.h | 12 + src/USER-PTM/ptm_constants.h | 174 ++ src/USER-PTM/ptm_functions.h | 27 + src/USER-PTM/quat.cpp | 396 +++++ src/USER-PTM/quat.h | 32 + src/USER-PTM/structure_matcher.cpp | 294 +++ src/USER-PTM/structure_matcher.h | 21 + 37 files changed, 7437 insertions(+) create mode 100644 doc/src/Eqs/ptm_rmsd.jpg create mode 100644 doc/src/Eqs/ptm_rmsd.tex create mode 100644 doc/src/compute_ptm_atom.txt create mode 100644 src/USER-PTM/LICENSE create mode 100644 src/USER-PTM/alloy_types.cpp create mode 100644 src/USER-PTM/alloy_types.h create mode 100644 src/USER-PTM/canonical_coloured.cpp create mode 100644 src/USER-PTM/canonical_coloured.h create mode 100644 src/USER-PTM/cell.cpp create mode 100644 src/USER-PTM/cell.h create mode 100644 src/USER-PTM/compute_ptm_atom.cpp create mode 100644 src/USER-PTM/compute_ptm_atom.h create mode 100644 src/USER-PTM/config.h create mode 100644 src/USER-PTM/convex_hull_incremental.cpp create mode 100644 src/USER-PTM/convex_hull_incremental.h create mode 100644 src/USER-PTM/deformation_gradient.cpp create mode 100644 src/USER-PTM/deformation_gradient.h create mode 100644 src/USER-PTM/fundamental_mappings.h create mode 100644 src/USER-PTM/graph_data.cpp create mode 100644 src/USER-PTM/graph_data.h create mode 100644 src/USER-PTM/graph_tools.cpp create mode 100644 src/USER-PTM/graph_tools.h create mode 100644 src/USER-PTM/index_ptm.cpp create mode 100644 src/USER-PTM/initialize_data.cpp create mode 100644 src/USER-PTM/initialize_data.h create mode 100644 src/USER-PTM/neighbour_ordering.cpp create mode 100644 src/USER-PTM/neighbour_ordering.h create mode 100644 src/USER-PTM/normalize_vertices.cpp create mode 100644 src/USER-PTM/normalize_vertices.h create mode 100644 src/USER-PTM/polar.cpp create mode 100644 src/USER-PTM/polar.h create mode 100644 src/USER-PTM/ptm_constants.h create mode 100644 src/USER-PTM/ptm_functions.h create mode 100644 src/USER-PTM/quat.cpp create mode 100644 src/USER-PTM/quat.h create mode 100644 src/USER-PTM/structure_matcher.cpp create mode 100644 src/USER-PTM/structure_matcher.h diff --git a/doc/src/Eqs/ptm_rmsd.jpg b/doc/src/Eqs/ptm_rmsd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2d20da706ef61194305123d5673042d2318aec23 GIT binary patch literal 6833 zcmcI|cT`l(vhSV&hKw^XGo&Hs%#fqxoQ51lvSbMolnjF8oIwdHS)za5O1Hr<^1%vQz76H6}_@FC20KhR8O$Go^ zozyL9G!5Uqfd12gv#APx(IQAR2mmlIigufmL=}i*G6k^0$*uvnG~@wq2+blMh)F8X^aq>*+dx*%ZwmVfS-%f18vZ|bCcXd*IE9mlsI)t~Jo7i*A z8tdJW1Eb&m@HXjK97_CPySLRzEInds77*TSHoI*|kr)RX{c{7*uJmOUT`b3D%*|5; zH$?__g>!lUfSlv>li?^oF>a(*Py%uM>R$~(Js+aWcKkEb{!y2}?N(8M?$&S|Pyh_V z27w{B*88Ukz{bG>Zr_mzVJM6gPA^M_!DSZV|F;!EIN(1QI#%DDYb>mlJR=ePaAOMH z|98?zwtn`{g^Kmrj^1;)71^}vmG8v7bD%&fkL>$V^R>`=n^Hcu?rSUBDEzvYbD;}3OT|y*FF80E1V)sxNgVzv%k%Mrsjv{Y~nJp za0*pg4McjAWLq+yptj+{%RyKJGh2$U_<~WH(j3_!Hln1m5GXo8#x&!j#1E?8-jU#) zHKiAzamE;Y5i8WtOI+p3oveP*vnS?<6sxXA8~_UDg|h~g_r6?l4Bk3;$7d)Ktc z>-Rgk4UMDoUB8C5^W-&snaw&`qU!l}T-STj_m90C8SKc(>kwR+eSWuyQh}ztOqLa= z83?g_hn`W=8KhE|55+zKVb0f4u%K8#sBL;ATSm-3?RiJV?fJ6 z;f%t%o+)Yc0@h(g5GHv&o7B2`ge>M!*FLkLf>-+634VQB@9^%)se^wz7(@nqWm)T6 zMh8o1xtsmFA3gIZSpHkZ=4Ir7;lw#%V&%(2avEcmbzX_;q(KXxdvwX~wp(NvJpaFo zA*t?Wt{i5a#I~=UC8^Pd<(c9MzEua!;WR6(1bUY_n{H9T?c`iP_^$Z;Ha`uz?{TTZ zV36E9uoV_y<4~4Un&MoNBx!a^BKvumML{cv63lHHbpOW{|AAcK8z!~pML$2{FMG2* zpXfUrYHjaYrvtIPdAX&PAuW@W z69w6^E@r4bG5)^vwV0ai)S}Wi&m2>`#NMEhM?%+W3cKin3$(75Pv( zjjH=+U)gi24p-=Ro0t={zDPRIFzPGnc}jyP5_ zskc4bnN58RM_&HqcRt_E`M5Z`AHG6Cfo~J^wV20S%0yb9G2ups~=q-b6!0ADlToEWMb>U`m#dHjGp5{6Q}Bs8 z@g8i2Z@oY5`Zy#FCgo^}Z||5g=ROhC-ZddMIl$rNJY%RrRvriUnVL|+IJ3g*9?13{ zN6!a{kbRChuW}(9^RA_qZ1R1ASY+<8NS#u7^XZRvfS6=^=7^Jcacl)X$E(zgS?2{- za;%3{ZV7Z3ts&`NvordrhEN#w_VVJ{%V@^BRF=o4kt6X+Lt^I&Mas5HI2Bg$L4=Fj z9saI;N(PH)7urmB*Ut#sR?C6f`>URq<2r6VEt~TI$nNv(qN}fYm)%xc$W);&V@~!+ zb3Uh~0l?Syo2H?b9JkO(36FV0zgq_PLx=wK$gPnfVb=__1k5#|>GSV}y{=)!X`ka6 zsf_}QZ8`CwKg?I8a(n$zLdRr=N-7K~pQ+FR{loP;BFkSJ?r9$B3pGa;(GDu48^Yz{8O)#zGtEl-C+SythaMN+3#~={KI|K z+??I@2I!uzeEr(~lP(21?cFXe9b3E^&%ow(^y^HKOsUbVV9ShmfgZ_JRveb7Kf6}# z0e{|yByw&NN2s=$U?ccH97Hg_k#gipE%RCgX5bl9wvg@6qUrTh8ccB*W8o|0|o1OAP@$35=ZO zw0Y*HEb5 zj<<0nnbELMANzfo?c6Y^R3StyHa;_KzG&(j<9M5%!iB-qZN&SH+yM74ikBq)PQ5l0 z&qG*+=0t|aBqUnDeiPBkj%|ODy?NvyEFyv+3La!jT)GyUI_O?tb#jgOr&09n4@;yH zBr<@dWGsZdnfb2g`-}YUveBz>@OVXkb>-BqeTQfK4KNc%b5BTEmAHG9!sAW{jgH(k zrOXr|5sVql+ow9)8Bk~Z+V=I6kIohLNgFu|OoR_dlt-NAE6auDpTs!p8K#)3N{Ozl z{cA~Ef6r3V)!@o&XpVj6h{s7 zi0g6kEaimVdwvm!zIT7@Yx!iZlFu$mQc23DlR^4}N)&z33&u!hC)O-}Muq&Qv7@CP zDisN(BTWWV*b^Qjgn#|Xn09c_$C7Y|c1+8@#dkR50k7c)Qg1<# zQ|b1&@ltiiC9b%*>fw#1%T~Un1X$6eN@;01sfJ*`S3@Kl=-jqswl3b(3U~B4vFK;F9%^}P3LF2J7UyviRvaid6GYvcB+@oz901Y4IO$* zAwcvrwW{8CKn1@JdE=d>>5q}4`Yb$>A`SKY0g{3Ih)2qqhTu*DTSN&sB=4ZKkwYpN4cNZyNtl6E#^b-pT^w@D3_VI<(6^wv|mI!e@}JHvf%VXQuglF8E@ zTkI<2_Rz%%1py!|Fb?)#$oCIwxkZ7u$1Po`by(Lvy=O|1Y#nCpfPdmYs6~e1(o+Ik zJbro}zdmWk|C#dv$;?-p%3ew1Xx|#>t|h}_t3u=dH5*eH8F~W@A2r;^YKirWXOXv5 zr$}cJFcoIG-SL>HNt#GE-4y&iA`?NOU46a10Ap36ecpv@+g?Y0kB~T&_}Mz%u95qv zmiAgo{x8mWcrcnbDgqWvdFfMOQqpLiZD#&%pnDJRq-uN_cP~t{4ljzVO5``0j@E)$ zHzR-ava+H(TLn^%`~D2I8$K(CyHr&kJyNcVRCQnM?TGnj@NBVtdIl*|in>UwXdh!7 z1C-mhS@{M4-ye}*&Dt)VR5XjZ`wk#h%)!9YIB_kp=hW55gEu>R zE?X`yG^Vh+aX3D1|5EnqzQZ(J#D~~Jjg@CCH&l42iGSIu2rs+p=o#M&r;q#b0gc`d zf0b}k@Mr5OyJt9r9NYGGuS(In`qs%0qt3<3tMJhLZ(C{#4^!$3%p&shsfXXde~AmK z)>a;Lb7E&dXd#s_pi9Z)pL%d#a^?j9e3xkOVlw7Pehiz(Z%fq~rRnU|%!_7P-%4}0 z*d5hUDJT}bKwS5M(%Cq1IM}vCl)n`le6=Sr>yYg4R$dM?+TLH{beS~xHIC}?or#q; z@GlH;DdeH|i>&M&HDhzTxr_#%^g~jx66Ldt32Ck1Jkgd)%W``O-= z%>+9R-G;BnqTefYkFRM3P7e|ZnG|njQ1V3O;-lxja7X6im*h5^kb>IIr0DKo-|ei^ z-6uF-ZGotrmWHCDLcu7lzIXJ&7@M7n<>|1EBW8YPQ|(5EfJ|0}`8(>NiSQi-+Yzd) zVPR`Kc2G-lK3X`HPZJG!NJy;g5$;7r?~RK^cTCQZKb^}IjL%wqJe>g)1#dV2yI|cymsQ9udvjNly_8tW2gfC3W1}{c8aYxz2gkrUMcrI4fN1!drpS8L-b+4H&v*f+^05>HiZcZxP%AkGp25Y zSM|3%{};LN`L=2MRt}rHCSs*+Izme3SJg_$RbarA%getaN7XX_)9HUx|Ni7Hs~2E{ z-UbBl-vq+O`d^U&s!MMz>zTrj2`j3b_z%_w$v`gy?33d|?@Y2^i7{pk`|Vg?&h4#q z1YceJ{y!=X0ubOqm$L1BSm-Q8b1H_gB601$$V?9$FX%QGz3Rhg%YIqF7~BGnZ`h{- zIO7y@rn1vTsds0<-SksalZ&} zj_B-^2jdmcLkkg{`@z@hiQ;_*aANQWO^TI-*BK0CD^qLcLS>7;RHJ7&)SQ3sK2yhw z8C+FwhlLQ_0Ad>nZe*nZD?9F+wRg%&F0BkW%cB>4O0??<3N@f+c=@ErJj1aAZ3!n; zTB_ACUCgdrQl_q~S5a}bsXJ$^$xgA;na9r$0SU%e)@Az`T9~*L($y-N*IC|Dlaw~) zvQK0^vI=LYQ_#!1LZlx#l>C#=)U|EESSTpd(V6K=^2s~F5`YPG2U^i1i>gk0Nz8X> zx!qg*1dNL7o_l|iuRvI9u?Sw(TMFIqO&J&A3Zn=uF|KED{Gw9Jh=vKcD~9?!j_^(0 zBX|C-T!`!{F{(~&rb%(F=#H^*u|$Hx@Om4=s$8W(3yZRJ4XF*Dpf89+e;r`IFB3a9#Xmsll%OjNOraEyUrip)!=R zE^k#RNF%M>u)YW?G53qLQ5kF;xR^2{CqsNWd#bVdLY&X-1G9wd+C~ zpT0g(lP?Ld1KYr_%r~8gid%?;0vaEA1r|YkjDEoZRPIRQHWutF5&)#Ut)g?15DK%5@ud>j@ zF{vtgoCS#k%dI|(r#_+3PEn4G3guRFRHXo!2oU7N6)WsMs}EInf9CH;sR|(#4pXf* z+i}P>qn(kEe&5rh#bE0JtIkwrWkozAl@n4uD!y8S3&o$Rhd6Mrr-vQR@E7Fj!XCya3;F0tHjHlL3DJ52DYvJ7HXDH^8J;PUQwDp=*?AuL2FiEBShHa0B>PHe}uc8=BQ! z2UB*RmyaX@Z1F8;>B&4tkP`d&PZGK~zs6QHj(H#VvKYuq!g}IZDwAl>Qy*<^c?d$H zJVSAfg_zOE-3J#KA`x7C7fx+q=c)*SWQC`rF_1ki$e>u~w?9rgnS!duvz%+Zp@Pq; zgp937%H!A=H}@;HiY!~fHL|xi_ke@}Bc3S%u__4tATXi4t4}#a{&hl32<+qc+ZAKd zTA;p7cdkuN)pG;bFkP0`AThX&!qO2}Ii{X{)mVest7-C5k`wJw5Kz-0X(E#a8&#+y z0Pr)BrLDXzdRCOhE&j+c#()=vITq{^E!7o`xEq>I!P?mP;h@U;NI=2OhqIK7<~+6^ ztQ59axOp~B5nl?dq%Z!^?ITgbHrU<<7*7W*0$g+R<-B z%oIu9GtgXfa`|SdYsDtWJ?(kUT9*&G&`%L2Lq=$s&zeO;=W?E-tP%1v+AwKl%6!wWo}lLg7hcEDo9V1?090CY zKj}b>Je +#include "ptm_constants.h" +#include "initialize_data.h" + + +#define NUM_ALLOY_TYPES 3 +static uint32_t typedata[NUM_ALLOY_TYPES][3] = { + {PTM_MATCH_FCC, PTM_ALLOY_L10, 0x000001fe}, + {PTM_MATCH_FCC, PTM_ALLOY_L12_CU, 0x0000001e}, + {PTM_MATCH_FCC, PTM_ALLOY_L12_AU, 0x00001ffe}, +}; + +static bool test_pure(int num_nbrs, int32_t* numbers) +{ + for (int i=1;inum_nbrs+1;i++) + binary[i] = numbers[mapping[i]] == numbers[0] ? 0 : 1; + + for (int i=1;inum_nbrs+1;i++) + if (binary[i] != binary[0]) + return false; + + return true; +} + +static int32_t canonical_alloy_representation(const refdata_t* ref, int8_t* mapping, int32_t* numbers) +{ + int8_t binary[PTM_MAX_POINTS]; + for (int i=0;inum_nbrs+1;i++) + binary[i] = numbers[mapping[i]] == numbers[0] ? 0 : 1; + + int8_t temp[PTM_MAX_POINTS]; + uint32_t best = 0xFFFFFFFF; + for (int j=0;jnum_mappings;j++) + { + for (int i=0;inum_nbrs+1;i++) + temp[ref->mapping[j][i]] = binary[i]; + + uint32_t code = 0; + for (int i=0;inum_nbrs+1;i++) + code |= (temp[i] << i); + + best = std::min(best, code); + } + + return best; +} + +int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers) +{ + if (test_pure(ref->num_nbrs, numbers)) + return PTM_ALLOY_PURE; + + if (!test_binary(ref->num_nbrs, numbers)) + return PTM_ALLOY_NONE; + + uint32_t code = canonical_alloy_representation(ref, mapping, numbers); + for (int i=0;itype == typedata[i][0] && code == typedata[i][2]) + return typedata[i][1]; + + if (ref->type == PTM_MATCH_BCC) + if (test_shell_structure(ref, mapping, numbers, 8)) + return PTM_ALLOY_B2; + + if (ref->type == PTM_MATCH_DCUB || ref->type == PTM_MATCH_DHEX) + if (test_shell_structure(ref, mapping, numbers, 4)) + return PTM_ALLOY_SIC; + + return PTM_ALLOY_NONE; +} + diff --git a/src/USER-PTM/alloy_types.h b/src/USER-PTM/alloy_types.h new file mode 100644 index 0000000000..1f2980593a --- /dev/null +++ b/src/USER-PTM/alloy_types.h @@ -0,0 +1,9 @@ +#ifndef ALLOY_TYPES_H +#define ALLOY_TYPES_H + +#include "initialize_data.h" + +int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers); + +#endif + diff --git a/src/USER-PTM/canonical_coloured.cpp b/src/USER-PTM/canonical_coloured.cpp new file mode 100644 index 0000000000..af446e1a95 --- /dev/null +++ b/src/USER-PTM/canonical_coloured.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include "graph_tools.h" +#include "ptm_constants.h" + + +static bool weinberg_coloured(int num_nodes, int num_edges, int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS], int8_t* colours, int8_t* best_code, int8_t* canonical_labelling, int a, int b) +{ + bool m[PTM_MAX_NBRS][PTM_MAX_NBRS]; + memset(m, 0, sizeof(bool) * PTM_MAX_NBRS * PTM_MAX_NBRS); + + int8_t index[PTM_MAX_NBRS]; + memset(index, -1, sizeof(int8_t) * PTM_MAX_NBRS); + + + int n = 0; + index[a] = colours[a] * num_nodes + n++; + if (index[a] > best_code[0]) + return false; + + bool winning = false; + if (index[a] < best_code[0]) + { + best_code[0] = index[a]; + winning = true; + } + + int c = -1; + for (int it=1;it<2*num_edges;it++) + { + bool newvertex = index[b] == -1; + + if (newvertex) + index[b] = colours[b] * num_nodes + n++; + + if (!winning && index[b] > best_code[it]) + return false; + + if (winning || index[b] < best_code[it]) + { + winning = true; + best_code[it] = index[b]; + } + + if (newvertex) + { + //When a new vertex is reached, take the right-most edge + //relative to the edge on which the vertex is reached. + + c = common[a][b]; + } + else if (m[b][a] == false) + { + //When an old vertex is reached on a new path, go back + //in the opposite direction. + + c = a; + } + else + { + //When an old vertex is reached on an old path, leave the + //vertex on the right-most edge that has not previously + //been traversed in that direction. + + c = common[a][b]; + while (m[b][c] == true) + c = common[c][b]; + } + + m[a][b] = true; + a = b; + b = c; + } + + if (winning) + { + memcpy(canonical_labelling, index, sizeof(int8_t) * num_nodes); + return true; + } + + return false; +} + +int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree, int8_t* colours, int8_t* canonical_labelling, int8_t* best_code, uint64_t* p_hash) +{ + int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS] = {{0}}; + int num_edges = 3 * num_facets / 2; + if (!build_facet_map(num_facets, facets, common)) + return -1; + + memset(best_code, SCHAR_MAX, sizeof(int8_t) * 2 * PTM_MAX_EDGES); + + bool equal = true; + for (int i = 1;i=0;i--) + canonical_labelling[i+1] = (canonical_labelling[i] % num_nodes) + 1; + canonical_labelling[0] = 0; + + uint64_t hash = 0; + for (int i = 0;i<2 * num_edges;i++) + { + uint64_t e = best_code[i]; + e += i % 8; + e &= 0xF; + e <<= (4 * i) % 64; + hash ^= e; + } + + *p_hash = hash; + return PTM_NO_ERROR; +} + diff --git a/src/USER-PTM/canonical_coloured.h b/src/USER-PTM/canonical_coloured.h new file mode 100644 index 0000000000..4a7b5f5a4a --- /dev/null +++ b/src/USER-PTM/canonical_coloured.h @@ -0,0 +1,9 @@ +#ifndef CANONICAL_COLOURED_H +#define CANONICAL_COLOURED_H + +#include + +int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree, int8_t* colours, int8_t* canonical_labelling, int8_t* best_code, uint64_t* p_hash); + +#endif + diff --git a/src/USER-PTM/cell.cpp b/src/USER-PTM/cell.cpp new file mode 100644 index 0000000000..f88e310b74 --- /dev/null +++ b/src/USER-PTM/cell.cpp @@ -0,0 +1,1368 @@ +// Voro++, a 3D cell-based Voronoi library +// +// Author : Chris H. Rycroft (LBL / UC Berkeley) +// Email : chr@alum.mit.edu +// Date : August 30th 2011 +// +// Modified by PM Larsen for use in Polyhedral Template Matching + +/** \file cell.cc + * \brief Function implementations for the voronoicell and related classes. */ + +#include +#include +#include +#include "config.h" +#include "cell.h" + +namespace voro { + +inline void voro_fatal_error(const char *p,int status) { + fprintf(stderr,"voro++: %s\n",p); + exit(status); + //return -1;//status; +} + +/** Constructs a Voronoi cell and sets up the initial memory. */ +voronoicell_base::voronoicell_base() : + current_vertices(init_vertices), current_vertex_order(init_vertex_order), + current_delete_size(init_delete_size), current_delete2_size(init_delete2_size), + ed(new int*[current_vertices]), nu(new int[current_vertices]), + pts(new double[3*current_vertices]), mem(new int[current_vertex_order]), + mec(new int[current_vertex_order]), mep(new int*[current_vertex_order]), + ds(new int[current_delete_size]), stacke(ds+current_delete_size), + ds2(new int[current_delete2_size]), stacke2(ds2+current_delete_size), + current_marginal(init_marginal), marg(new int[current_marginal]) { + int i; + for(i=0;i<3;i++) { + mem[i]=init_n_vertices;mec[i]=0; + mep[i]=new int[init_n_vertices*((i<<1)+1)]; + } + mem[3]=init_3_vertices;mec[3]=0; + mep[3]=new int[init_3_vertices*7]; + for(i=4;i=0;i--) if(mem[i]>0) delete [] mep[i]; + delete [] marg; + delete [] ds2;delete [] ds; + delete [] mep;delete [] mec; + delete [] mem;delete [] pts; + delete [] nu;delete [] ed; +} + +/** Ensures that enough memory is allocated prior to carrying out a copy. + * \param[in] vc a reference to the specialized version of the calling class. + * \param[in] vb a pointered to the class to be copied. */ +template +void voronoicell_base::check_memory_for_copy(vc_class &vc,voronoicell_base* vb) { + while(current_vertex_ordercurrent_vertex_order) add_memory_vorder(vc); + for(int i=0;imec[i]) add_memory(vc,i,ds2); + while(current_verticesp) add_memory_vertices(vc); +} + +/** Increases the memory storage for a particular vertex order, by increasing + * the size of the of the corresponding mep array. If the arrays already exist, + * their size is doubled; if they don't exist, then new ones of size + * init_n_vertices are allocated. The routine also ensures that the pointers in + * the ed array are updated, by making use of the back pointers. For the cases + * where the back pointer has been temporarily overwritten in the marginal + * vertex code, the auxiliary delete stack is scanned to find out how to update + * the ed value. If the template has been instantiated with the neighbor + * tracking turned on, then the routine also reallocates the corresponding mne + * array. + * \param[in] i the order of the vertex memory to be increased. */ +template +void voronoicell_base::add_memory(vc_class &vc,int i,int *stackp2) { + int s=(i<<1)+1; + if(mem[i]==0) { + vc.n_allocate(i,init_n_vertices); + mep[i]=new int[init_n_vertices*s]; + mem[i]=init_n_vertices; +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Order %d vertex memory created\n",i); +#endif + } else { + int j=0,k,*l; + mem[i]<<=1; + if(mem[i]>max_n_vertices) voro_fatal_error("Point memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Order %d vertex memory scaled up to %d\n",i,mem[i]); +#endif + l=new int[s*mem[i]]; + int m=0; + vc.n_allocate_aux1(i); + while(j=0) { + ed[k]=l+j; + vc.n_set_to_aux1_offset(k,m); + } else { + int *dsp; + for(dsp=ds2;dsp=3 + fputs("Relocated dangling pointer",stderr); +#endif + } + for(k=0;k +void voronoicell_base::add_memory_vertices(vc_class &vc) { + +printf("nope: %d\n", current_vertices); +exit(3); + + int i=(current_vertices<<1),j,**pp,*pnu; + if(i>max_vertices) voro_fatal_error("Vertex memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Vertex memory scaled up to %d\n",i); +#endif + double *ppts; + pp=new int*[i]; + for(j=0;j +void voronoicell_base::add_memory_vorder(vc_class &vc) { + int i=(current_vertex_order<<1),j,*p1,**p2; + if(i>max_vertex_order) voro_fatal_error("Vertex order memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Vertex order memory scaled up to %d\n",i); +#endif + p1=new int[i]; + for(j=0;jmax_delete_size) voro_fatal_error("Delete stack 1 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Delete stack 1 memory scaled up to %d\n",current_delete_size); +#endif + int *dsn=new int[current_delete_size],*dsnp=dsn,*dsp=ds; + while(dspmax_delete2_size) voro_fatal_error("Delete stack 2 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Delete stack 2 memory scaled up to %d\n",current_delete2_size); +#endif + int *dsn=new int[current_delete2_size],*dsnp=dsn,*dsp=ds2; + while(dsp +inline bool voronoicell_base::search_for_outside_edge(vc_class &vc,int &up) { + int i,lp,lw,*j(ds2),*stackp2(ds2); + double l; + *(stackp2++)=up; + while(j +inline void voronoicell_base::add_to_stack(vc_class &vc,int lp,int *&stackp2) { + for(int *k(ds2);k +bool voronoicell_base::nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id) { + int count=0,i,j,k,lp=up,cp,qp,rp,*stackp(ds),*stackp2(ds2),*dsp; + int us=0,ls=0,qs,iqs,cs,uw,qw,lw; + int *edp,*edd; + double u,l,r,q;bool complicated_setup=false,new_double_edge=false,double_edge=false; + + // Initialize the safe testing routine + n_marg=0;px=x;py=y;pz=z;prsq=rsq; + + // Test approximately sqrt(n)/4 points for their proximity to the plane + // and keep the one which is closest + uw=m_test(up,u); + + // Starting from an initial guess, we now move from vertex to vertex, + // to try and find an edge which intersects the cutting plane, + // or a vertex which is on the plane + try { + if(uw==1) { + + // The test point is inside the cutting plane. + us=0; + do { + lp=ed[up][us]; + lw=m_test(lp,l); + if(l=p) throw true; + u=l;up=lp; + for(us=0;us=p) throw true; + u=q;up=qp; + for(us=0;us=1 + fputs("Bailed out of convex calculation\n",stderr); +#endif + qw=1;lw=0; + for(qp=0;qp=current_vertex_order) add_memory_vorder(vc); + if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); + vc.n_set_pointer(p,nu[p]); + ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; + ed[p][nu[p]<<1]=p; + + // Copy the edges of the original vertex into the new + // one. Delete the edges of the original vertex, and + // update the relational table. + us=cycle_down(i,up); + while(i=current_vertex_order) add_memory_vorder(vc); + if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); + + // Copy the edges of the original vertex into the new + // one. Delete the edges of the original vertex, and + // update the relational table. + vc.n_set_pointer(p,nu[p]); + ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; + ed[p][nu[p]<<1]=p; + us=i++; + while(i0) k+=nu[j]; + } else { + if(j>0) { + + // This vertex was visited before, so + // count those vertices to the ones we + // already have. + k+=nu[j]; + + // The only time when we might make a + // duplicate edge is if the point we're + // going to move to next is also a + // marginal point, so test for that + // first. + if(lw==0) { + + // Now see whether this marginal point + // has been visited before. + i=-ed[lp][nu[lp]<<1]; + if(i>0) { + + // Now see if the last edge of that other + // marginal point actually ends up here. + if(ed[i][nu[i]-1]==j) { + new_double_edge=true; + k-=1; + } else new_double_edge=false; + } else { + + // That marginal point hasn't been visited + // before, so we probably don't have to worry + // about duplicate edges, except in the + // case when that's the way into the end + // of the facet, because that way always creates + // an edge. + if(j==rp&&lp==up&&ed[qp][nu[qp]+qs]==us) { + new_double_edge=true; + k-=1; + } else new_double_edge=false; + } + } else new_double_edge=false; + } else { + + // The vertex hasn't been visited + // before, but let's see if it's + // marginal + if(lw==0) { + + // If it is, we need to check + // for the case that it's a + // small branch, and that we're + // heading right back to where + // we came from + i=-ed[lp][nu[lp]<<1]; + if(i==cp) { + new_double_edge=true; + k-=1; + } else new_double_edge=false; + } else new_double_edge=false; + } + } + + // k now holds the number of edges of the new vertex + // we are forming. Add memory for it if it doesn't exist + // already. + while(k>=current_vertex_order) add_memory_vorder(vc); + if(mec[k]==mem[k]) add_memory(vc,k,stackp2); + + // Now create a new vertex with order k, or augment + // the existing one + if(j>0) { + + // If we're augmenting a vertex but we don't + // actually need any more edges, just skip this + // routine to avoid memory confusion + if(nu[j]!=k) { + // Allocate memory and copy the edges + // of the previous instance into it + vc.n_set_aux1(k); + edp=mep[k]+((k<<1)+1)*mec[k]++; + i=0; + while(ids) { + --p; + while(ed[p][nu[p]]==-1) { + j=nu[p]; + edp=ed[p];edd=(mep[j]+((j<<1)+1)*--mec[j]); + while(edp0) voro_fatal_error("Zero order vertex formed",VOROPP_INTERNAL_ERROR); + + // Collapse any order 2 vertices and exit + return collapse_order2(vc); +} + +/** During the creation of a new facet in the plane routine, it is possible + * that some order two vertices may arise. This routine removes them. + * Suppose an order two vertex joins c and d. If there's a edge between + * c and d already, then the order two vertex is just removed; otherwise, + * the order two vertex is removed and c and d are joined together directly. + * It is possible this process will create order two or order one vertices, + * and the routine is continually run until all of them are removed. + * \return False if the vertex removal was unsuccessful, indicative of the cell + * reducing to zero volume and disappearing; true if the vertex removal + * was successful. */ +template +inline bool voronoicell_base::collapse_order2(vc_class &vc) { + if(!collapse_order1(vc)) return false; + int a,b,i,j,k,l; + while(mec[2]>0) { + + // Pick a order 2 vertex and read in its edges + i=--mec[2]; + j=mep[2][5*i];k=mep[2][5*i+1]; + if(j==k) { +#if VOROPP_VERBOSE >=1 + fputs("Order two vertex joins itself",stderr); +#endif + return false; + } + + // Scan the edges of j to see if joins k + for(l=0;l +inline bool voronoicell_base::collapse_order1(vc_class &vc) { + int i,j,k; + while(mec[1]>0) { + up=0; +#if VOROPP_VERBOSE >=1 + fputs("Order one collapse\n",stderr); +#endif + i=--mec[1]; + j=mep[1][3*i];k=mep[1][3*i+1]; + i=mep[1][3*i+2]; + if(!delete_connection(vc,j,k,false)) return false; + --p; + if(up==i) up=0; + if(p!=i) { + if(up==p) up=i; + pts[3*i]=pts[3*p]; + pts[3*i+1]=pts[3*p+1]; + pts[3*i+2]=pts[3*p+2]; + for(k=0;k +inline bool voronoicell_base::delete_connection(vc_class &vc,int j,int k,bool hand) { + int q=hand?k:cycle_up(k,j); + int i=nu[j]-1,l,*edp,*edd,m; +#if VOROPP_VERBOSE >=1 + if(i<1) { + fputs("Zero order vertex formed\n",stderr); + return false; + } +#endif + if(mec[i]==mem[i]) add_memory(vc,i,ds2); + vc.n_set_aux1(i); + for(l=0;l &v) { + double area; + v.clear(); + int i,j,k,l,m,n; + double ux,uy,uz,vx,vy,vz,wx,wy,wz; + for(i=1;i=0) { + area=0; + ed[i][j]=-1-k; + l=cycle_up(ed[i][nu[i]+j],k); + m=ed[k][l];ed[k][l]=-1-m; + while(m!=i) { + n=cycle_up(ed[k][nu[k]+l],m); + ux=pts[3*k]-pts[3*i]; + uy=pts[3*k+1]-pts[3*i+1]; + uz=pts[3*k+2]-pts[3*i+2]; + vx=pts[3*m]-pts[3*i]; + vy=pts[3*m+1]-pts[3*i+1]; + vz=pts[3*m+2]-pts[3*i+2]; + wx=uy*vz-uz*vy; + wy=uz*vx-ux*vz; + wz=ux*vy-uy*vx; + area+=sqrt(wx*wx+wy*wy+wz*wz); + k=m;l=n; + m=ed[k][l];ed[k][l]=-1-m; + } + v.push_back(0.125*area); + } + } + reset_edges(); +} + +/** Several routines in the class that gather cell-based statistics internally + * track their progress by flipping edges to negative so that they know what + * parts of the cell have already been tested. This function resets them back + * to positive. When it is called, it assumes that every edge in the routine + * should have already been flipped to negative, and it bails out with an + * internal error if it encounters a positive edge. */ +inline void voronoicell_base::reset_edges() { + int i,j; + for(i=0;i=0) voro_fatal_error("Edge reset routine found a previously untested edge",VOROPP_INTERNAL_ERROR); + ed[i][j]=-1-ed[i][j]; + } +} + +/** Checks to see if a given vertex is inside, outside or within the test + * plane. If the point is far away from the test plane, the routine immediately + * returns whether it is inside or outside. If the routine is close the the + * plane and within the specified tolerance, then the special check_marginal() + * routine is called. + * \param[in] n the vertex to test. + * \param[out] ans the result of the scalar product used in evaluating the + * location of the point. + * \return -1 if the point is inside the plane, 1 if the point is outside the + * plane, or 0 if the point is within the plane. */ +inline int voronoicell_base::m_test(int n,double &ans) { + double *pp=pts+n+(n<<1); + ans=*(pp++)*px; + ans+=*(pp++)*py; + ans+=*pp*pz-prsq; + if(ans<-tolerance2) { + return -1; + } else if(ans>tolerance2) { + return 1; + } + return check_marginal(n,ans); +} + +/** Checks to see if a given vertex is inside, outside or within the test + * plane, for the case when the point has been detected to be very close to the + * plane. The routine ensures that the returned results are always consistent + * with previous tests, by keeping a table of any marginal results. The routine + * first sees if the vertex is in the table, and if it finds a previously + * computed result it uses that. Otherwise, it computes a result for this + * vertex and adds it the table. + * \param[in] n the vertex to test. + * \param[in] ans the result of the scalar product used in evaluating + * the location of the point. + * \return -1 if the point is inside the plane, 1 if the point is outside the + * plane, or 0 if the point is within the plane. */ +int voronoicell_base::check_marginal(int n,double &ans) { + int i; + for(i=0;imax_marginal) + voro_fatal_error("Marginal case buffer allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Marginal cases buffer scaled up to %d\n",i); +#endif + int *pmarg=new int[current_marginal]; + for(int j=0;jtolerance?1:(ans<-tolerance?-1:0); + return marg[n_marg-1]; +} + +/** This initializes the class to be a rectangular box. It calls the base class + * initialization routine to set up the edge and vertex information, and then + * sets up the neighbor information, with initial faces being assigned ID + * numbers from -1 to -6. + * \param[in] (xmin,xmax) the minimum and maximum x coordinates. + * \param[in] (ymin,ymax) the minimum and maximum y coordinates. + * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */ +void voronoicell_neighbor::init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) { + init_base(xmin,xmax,ymin,ymax,zmin,zmax); + int *q=mne[3]; + *q=-5;q[1]=-3;q[2]=-1; + q[3]=-5;q[4]=-2;q[5]=-3; + q[6]=-5;q[7]=-1;q[8]=-4; + q[9]=-5;q[10]=-4;q[11]=-2; + q[12]=-6;q[13]=-1;q[14]=-3; + q[15]=-6;q[16]=-3;q[17]=-2; + q[18]=-6;q[19]=-4;q[20]=-1; + q[21]=-6;q[22]=-2;q[23]=-4; + *ne=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9; + ne[4]=q+12;ne[5]=q+15;ne[6]=q+18;ne[7]=q+21; +} + +/** This routine checks to make sure the neighbor information of each face is + * consistent. */ +void voronoicell_neighbor::check_facets() { + int i,j,k,l,m,q; + for(i=1;i=0) { + ed[i][j]=-1-k; + q=ne[i][j]; + l=cycle_up(ed[i][nu[i]+j],k); + do { + m=ed[k][l]; + ed[k][l]=-1-m; + if(ne[k][l]!=q) fprintf(stderr,"Facet error at (%d,%d)=%d, started from (%d,%d)=%d\n",k,l,ne[k][l],i,j,q); + l=cycle_up(ed[k][nu[k]+l],m); + k=m; + } while (k!=i); + } + } + reset_edges(); +} + +/** The class constructor allocates memory for storing neighbor information. */ +voronoicell_neighbor::voronoicell_neighbor() { + int i; + mne=new int*[current_vertex_order]; + ne=new int*[current_vertices]; + for(i=0;i<3;i++) mne[i]=new int[init_n_vertices*i]; + mne[3]=new int[init_3_vertices*3]; + for(i=4;i=0;i--) if(mem[i]>0) delete [] mne[i]; + delete [] mne; + delete [] ne; +} + +/** Computes a vector list of neighbors. */ +void voronoicell_neighbor::neighbors(std::vector &v) { + v.clear(); + int i,j,k,l,m; + for(i=1;i=0) { + v.push_back(ne[i][j]); + ed[i][j]=-1-k; + l=cycle_up(ed[i][nu[i]+j],k); + do { + m=ed[k][l]; + ed[k][l]=-1-m; + l=cycle_up(ed[k][nu[k]+l],m); + k=m; + } while (k!=i); + } + } + reset_edges(); +} + +// Explicit instantiation +template bool voronoicell_base::nplane(voronoicell_neighbor&,double,double,double,double,int); +template void voronoicell_base::check_memory_for_copy(voronoicell_neighbor&,voronoicell_base*); + +} + diff --git a/src/USER-PTM/cell.h b/src/USER-PTM/cell.h new file mode 100644 index 0000000000..51a0cbb9ef --- /dev/null +++ b/src/USER-PTM/cell.h @@ -0,0 +1,324 @@ +// Voro++, a 3D cell-based Voronoi library +// +// Author : Chris H. Rycroft (LBL / UC Berkeley) +// Email : chr@alum.mit.edu +// Date : August 30th 2011 +// +// Modified by PM Larsen for use in Polyhedral Template Matching + +/** \file cell.hh + * \brief Header file for the voronoicell and related classes. */ + +#ifndef VOROPP_CELL_HH +#define VOROPP_CELL_HH + +#include +#include + +#include "config.h" + +namespace voro { + +/** \brief A class representing a single Voronoi cell. + * + * This class represents a single Voronoi cell, as a collection of vertices + * that are connected by edges. The class contains routines for initializing + * the Voronoi cell to be simple shapes such as a box, tetrahedron, or octahedron. + * It the contains routines for recomputing the cell based on cutting it + * by a plane, which forms the key routine for the Voronoi cell computation. + * It contains numerous routine for computing statistics about the Voronoi cell, + * and it can output the cell in several formats. + * + * This class is not intended for direct use, but forms the base of the + * voronoicell and voronoicell_neighbor classes, which extend it based on + * whether neighboring particle ID information needs to be tracked. */ +class voronoicell_base { + public: + /** This holds the current size of the arrays ed and nu, which + * hold the vertex information. If more vertices are created + * than can fit in this array, then it is dynamically extended + * using the add_memory_vertices routine. */ + int current_vertices; + /** This holds the current maximum allowed order of a vertex, + * which sets the size of the mem, mep, and mec arrays. If a + * vertex is created with more vertices than this, the arrays + * are dynamically extended using the add_memory_vorder routine. + */ + int current_vertex_order; + /** This sets the size of the main delete stack. */ + int current_delete_size; + /** This sets the size of the auxiliary delete stack. */ + int current_delete2_size; + /** This sets the total number of vertices in the current cell. + */ + int p; + /** This is the index of particular point in the cell, which is + * used to start the tracing routines for plane intersection + * and cutting. These routines will work starting from any + * point, but it's often most efficient to start from the last + * point considered, since in many cases, the cell construction + * algorithm may consider many planes with similar vectors + * concurrently. */ + int up; + /** This is a two dimensional array that holds information + * about the edge connections of the vertices that make up the + * cell. The two dimensional array is not allocated in the + * usual method. To account for the fact the different vertices + * have different orders, and thus require different amounts of + * storage, the elements of ed[i] point to one-dimensional + * arrays in the mep[] array of different sizes. + * + * More specifically, if vertex i has order m, then ed[i] + * points to a one-dimensional array in mep[m] that has 2*m+1 + * entries. The first m elements hold the neighboring edges, so + * that the jth edge of vertex i is held in ed[i][j]. The next + * m elements hold a table of relations which is redundant but + * helps speed up the computation. It satisfies the relation + * ed[ed[i][j]][ed[i][m+j]]=i. The final entry holds a back + * pointer, so that ed[i+2*m]=i. The back pointers are used + * when rearranging the memory. */ + int **ed; + /** This array holds the order of the vertices in the Voronoi + * cell. This array is dynamically allocated, with its current + * size held by current_vertices. */ + int *nu; + /** This in an array with size 3*current_vertices for holding + * the positions of the vertices. */ + double *pts; + voronoicell_base(); + virtual ~voronoicell_base(); + void init_base(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); + void init_octahedron_base(double l); + void init_tetrahedron_base(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3); + void translate(double x,double y,double z); + double volume(); + double max_radius_squared(); + double total_edge_distance(); + double surface_area(); + void centroid(double &cx,double &cy,double &cz); + int number_of_faces(); + int number_of_edges(); + void vertex_orders(std::vector &v); + void vertices(std::vector &v); + void vertices(double x,double y,double z,std::vector &v); + void face_areas(std::vector &v); + void face_orders(std::vector &v); + void face_freq_table(std::vector &v); + void face_vertices(std::vector &v); + void face_perimeters(std::vector &v); + void normals(std::vector &v); + template + bool nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id); + bool plane_intersects(double x,double y,double z,double rsq); + bool plane_intersects_guess(double x,double y,double z,double rsq); + void construct_relations(); + void check_relations(); + void check_duplicates(); + /** Returns a list of IDs of neighboring particles + * corresponding to each face. + * \param[out] v a reference to a vector in which to return the + * results. If no neighbor information is + * available, a blank vector is returned. */ + virtual void neighbors(std::vector &v) {v.clear();} + /** This a virtual function that is overridden by a routine to + * print the neighboring particle IDs for a given vertex. By + * default, when no neighbor information is available, the + * routine does nothing. + * \param[in] i the vertex to consider. */ + /** This is a simple inline function for picking out the index + * of the next edge counterclockwise at the current vertex. + * \param[in] a the index of an edge of the current vertex. + * \param[in] p the number of the vertex. + * \return 0 if a=nu[p]-1, or a+1 otherwise. */ + inline int cycle_up(int a,int p) {return a==nu[p]-1?0:a+1;} + /** This is a simple inline function for picking out the index + * of the next edge clockwise from the current vertex. + * \param[in] a the index of an edge of the current vertex. + * \param[in] p the number of the vertex. + * \return nu[p]-1 if a=0, or a-1 otherwise. */ + inline int cycle_down(int a,int p) {return a==0?nu[p]-1:a-1;} + protected: + /** This a one dimensional array that holds the current sizes + * of the memory allocations for them mep array.*/ + int *mem; + /** This is a one dimensional array that holds the current + * number of vertices of order p that are stored in the mep[p] + * array. */ + int *mec; + /** This is a two dimensional array for holding the information + * about the edges of the Voronoi cell. mep[p] is a + * one-dimensional array for holding the edge information about + * all vertices of order p, with each vertex holding 2*p+1 + * integers of information. The total number of vertices held + * on mep[p] is stored in mem[p]. If the space runs out, the + * code allocates more using the add_memory() routine. */ + int **mep; + inline void reset_edges(); + template + void check_memory_for_copy(vc_class &vc,voronoicell_base* vb); + void copy(voronoicell_base* vb); + private: + /** This is the delete stack, used to store the vertices which + * are going to be deleted during the plane cutting procedure. + */ + int *ds,*stacke; + /** This is the auxiliary delete stack, which has size set by + * current_delete2_size. */ + int *ds2,*stacke2; + /** This stores the current memory allocation for the marginal + * cases. */ + int current_marginal; + /** This stores the total number of marginal points which are + * currently in the buffer. */ + int n_marg; + /** This array contains a list of the marginal points, and also + * the outcomes of the marginal tests. */ + int *marg; + /** The x coordinate of the normal vector to the test plane. */ + double px; + /** The y coordinate of the normal vector to the test plane. */ + double py; + /** The z coordinate of the normal vector to the test plane. */ + double pz; + /** The magnitude of the normal vector to the test plane. */ + double prsq; + template + void add_memory(vc_class &vc,int i,int *stackp2); + template + void add_memory_vertices(vc_class &vc); + template + void add_memory_vorder(vc_class &vc); + void add_memory_ds(int *&stackp); + void add_memory_ds2(int *&stackp2); + template + inline bool collapse_order1(vc_class &vc); + template + inline bool collapse_order2(vc_class &vc); + template + inline bool delete_connection(vc_class &vc,int j,int k,bool hand); + template + inline bool search_for_outside_edge(vc_class &vc,int &up); + template + inline void add_to_stack(vc_class &vc,int lp,int *&stackp2); + inline bool plane_intersects_track(double x,double y,double z,double rs,double g); + inline void normals_search(std::vector &v,int i,int j,int k); + inline bool search_edge(int l,int &m,int &k); + inline int m_test(int n,double &ans); + int check_marginal(int n,double &ans); + friend class voronoicell; + friend class voronoicell_neighbor; +}; + +/** \brief Extension of the voronoicell_base class to represent a Voronoi cell + * with neighbor information. + * + * This class is an extension of the voronoicell_base class, in cases when the + * IDs of neighboring particles associated with each face of the Voronoi cell. + * It contains additional data structures mne and ne for storing this + * information. */ +class voronoicell_neighbor : public voronoicell_base { + public: + using voronoicell_base::nplane; + /** This two dimensional array holds the neighbor information + * associated with each vertex. mne[p] is a one dimensional + * array which holds all of the neighbor information for + * vertices of order p. */ + int **mne; + /** This is a two dimensional array that holds the neighbor + * information associated with each vertex. ne[i] points to a + * one-dimensional array in mne[nu[i]]. ne[i][j] holds the + * neighbor information associated with the jth edge of vertex + * i. It is set to the ID number of the plane that made the + * face that is clockwise from the jth edge. */ + int **ne; + voronoicell_neighbor(); + ~voronoicell_neighbor(); + void operator=(voronoicell_neighbor &c); + /** Cuts the Voronoi cell by a particle whose center is at a + * separation of (x,y,z) from the cell center. The value of rsq + * should be initially set to \f$x^2+y^2+z^2\f$. + * \param[in] (x,y,z) the normal vector to the plane. + * \param[in] rsq the distance along this vector of the plane. + * \param[in] p_id the plane ID (for neighbor tracking only). + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool nplane(double x,double y,double z,double rsq,int p_id) { + return nplane(*this,x,y,z,rsq,p_id); + } + /** This routine calculates the modulus squared of the vector + * before passing it to the main nplane() routine with full + * arguments. + * \param[in] (x,y,z) the vector to cut the cell by. + * \param[in] p_id the plane ID (for neighbor tracking only). + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool nplane(double x,double y,double z,int p_id) { + double rsq=x*x+y*y+z*z; + return nplane(*this,x,y,z,rsq,p_id); + } + /** This version of the plane routine just makes up the plane + * ID to be zero. It will only be referenced if neighbor + * tracking is enabled. + * \param[in] (x,y,z) the vector to cut the cell by. + * \param[in] rsq the modulus squared of the vector. + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool plane(double x,double y,double z,double rsq) { + return nplane(*this,x,y,z,rsq,0); + } + /** Cuts a Voronoi cell using the influence of a particle at + * (x,y,z), first calculating the modulus squared of this + * vector before passing it to the main nplane() routine. Zero + * is supplied as the plane ID, which will be ignored unless + * neighbor tracking is enabled. + * \param[in] (x,y,z) the vector to cut the cell by. + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool plane(double x,double y,double z) { + double rsq=x*x+y*y+z*z; + return nplane(*this,x,y,z,rsq,0); + } + void init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); + void check_facets(); + virtual void neighbors(std::vector &v); + + private: + int *paux1; + int *paux2; + inline void n_allocate(int i,int m) {mne[i]=new int[m*i];} + inline void n_add_memory_vertices(int i) { + int **pp=new int*[i]; + for(int j=0;j +#include +#include +#include + +#include "atom.h" +#include "comm.h" +#include "compute_ptm_atom.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "modify.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "neighbor.h" +#include "pair.h" +#include "update.h" + +#include "ptm_functions.h" + +#define MAX_NEIGHBORS 30 +#define NUM_COLUMNS 7 +#define UNKNOWN 0 +#define OTHER 8 + +using namespace LAMMPS_NS; + +static const char cite_user_ptm_package[] = + "USER-PTM package:\n\n" + "@Article{larsen2016ptm,\n" + " author={Larsen, Peter Mahler and Schmidt, S{\o}ren and Schi{\o}tz, " + "Jakob},\n" + " title={Robust structural identification via polyhedral template " + "matching},\n" + " journal={Modelling~Simul.~Mater.~Sci.~Eng.},\n" + " year={2016},\n" + " number={5},\n" + " volume={24},\n" + " pages={055007},\n" + " DOI = {10.1088/0965-0393/24/5/055007}" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +ComputePTMAtom::ComputePTMAtom(LAMMPS *lmp, int narg, char **arg) + : Compute(lmp, narg, arg), list(NULL), output(NULL) { + if (narg != 5) + error->all(FLERR, "Illegal compute ptm/atom command"); + + char *structures = arg[3]; + char *ptr = structures; + + const char *strings[] = {"fcc", "hcp", "bcc", "ico", "sc", + "dcub", "dhex", "all", "default"}; + int32_t flags[] = { + PTM_CHECK_FCC, + PTM_CHECK_HCP, + PTM_CHECK_BCC, + PTM_CHECK_ICO, + PTM_CHECK_SC, + PTM_CHECK_DCUB, + PTM_CHECK_DHEX, + PTM_CHECK_ALL, + PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_BCC | PTM_CHECK_ICO}; + + input_flags = 0; + while (*ptr != '\0') { + + bool found = false; + for (int i = 0; i < 9; i++) { + int len = strlen(strings[i]); + if (strncmp(ptr, strings[i], len) == 0) { + input_flags |= flags[i]; + ptr += len; + found = true; + break; + } + } + + if (!found) + error->all(FLERR, + "Illegal compute ptm/atom command (invalid structure type)"); + + if (*ptr == '\0') + break; + + if (*ptr != '-') + error->all(FLERR, + "Illegal compute ptm/atom command (invalid structure type)"); + + ptr++; + } + + double threshold = force->numeric(FLERR, arg[4]); + if (threshold < 0.0) + error->all(FLERR, + "Illegal compute ptm/atom command (threshold is negative)"); + rmsd_threshold = threshold; + if (rmsd_threshold == 0) + rmsd_threshold = INFINITY; + + peratom_flag = 1; + size_peratom_cols = NUM_COLUMNS; + create_attribute = 1; + nmax = 0; +} + +/* ---------------------------------------------------------------------- */ + +ComputePTMAtom::~ComputePTMAtom() { memory->destroy(output); } + +/* ---------------------------------------------------------------------- */ + +void ComputePTMAtom::init() { + if (force->pair == NULL) + error->all(FLERR, "Compute ptm/atom requires a pair style be defined"); + + int count = 0; + for (int i = 0; i < modify->ncompute; i++) + if (strcmp(modify->compute[i]->style, "ptm/atom") == 0) + count++; + if (count > 1 && comm->me == 0) + error->warning(FLERR, "More than one compute ptm/atom defined"); + + // need an occasional full neighbor list + + int irequest = neighbor->request(this, instance_me); + neighbor->requests[irequest]->pair = 0; + neighbor->requests[irequest]->compute = 1; + neighbor->requests[irequest]->half = 0; + neighbor->requests[irequest]->full = 1; + neighbor->requests[irequest]->occasional = 1; +} + +/* ---------------------------------------------------------------------- */ + +void ComputePTMAtom::init_list(int id, NeighList *ptr) { list = ptr; } + +/* ---------------------------------------------------------------------- */ + +typedef struct { + int index; + double d; +} ptmnbr_t; + +static bool sorthelper_compare(ptmnbr_t const &a, ptmnbr_t const &b) { + return a.d < b.d; +} + +static int get_neighbors(double *pos, int jnum, int *jlist, double **x, + double (*nbr)[3]) { + + ptmnbr_t *nbr_order = new ptmnbr_t[jnum]; + + for (int jj = 0; jj < jnum; jj++) { + int j = jlist[jj]; + j &= NEIGHMASK; + + double dx = pos[0] - x[j][0]; + double dy = pos[1] - x[j][1]; + double dz = pos[2] - x[j][2]; + double rsq = dx * dx + dy * dy + dz * dz; + + nbr_order[jj].index = j; + nbr_order[jj].d = rsq; + } + + std::sort(nbr_order, nbr_order + jnum, &sorthelper_compare); + int num_nbrs = std::min(MAX_NEIGHBORS, jnum); + + nbr[0][0] = nbr[0][1] = nbr[0][2] = 0; + for (int jj = 0; jj < num_nbrs; jj++) { + + int j = nbr_order[jj].index; + nbr[jj + 1][0] = x[j][0] - pos[0]; + nbr[jj + 1][1] = x[j][1] - pos[1]; + nbr[jj + 1][2] = x[j][2] - pos[2]; + } + + delete[] nbr_order; + return num_nbrs; +} + +void ComputePTMAtom::compute_peratom() { + // PTM global initialization. If already initialized this function does + // nothing. + ptm_initialize_global(); + + // initialize PTM local storage + ptm_local_handle_t local_handle = ptm_initialize_local(); + + invoked_peratom = update->ntimestep; + + // grow arrays if necessary + if (atom->nmax > nmax) { + memory->destroy(output); + nmax = atom->nmax; + + memory->create(output, nmax, NUM_COLUMNS, "ptm:ptm_output"); + array_atom = output; + } + + // invoke full neighbor list (will copy or build if necessary) + neighbor->build_one(list); + + int inum = list->inum; + int *ilist = list->ilist; + int *numneigh = list->numneigh; + int **firstneigh = list->firstneigh; + + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int ii = 0; ii < inum; ii++) { + + int i = ilist[ii]; + output[i][0] = UNKNOWN; + if (!(mask[i] & groupbit)) + continue; + + double *pos = x[i]; + + int *jlist = firstneigh[i]; + int jnum = numneigh[i]; + if (jnum <= 0) + continue; + + // get neighbours ordered by increasing distance + double nbr[MAX_NEIGHBORS + 1][3]; + int num_nbrs = get_neighbors(pos, jnum, jlist, x, nbr); + + // check that we have enough neighbours for the desired structure types + int32_t flags = 0; + if (num_nbrs >= PTM_NUM_NBRS_SC && (input_flags & PTM_CHECK_SC)) + flags |= PTM_CHECK_SC; + if (num_nbrs >= PTM_NUM_NBRS_FCC && (input_flags & PTM_CHECK_FCC)) + flags |= PTM_CHECK_FCC; + if (num_nbrs >= PTM_NUM_NBRS_HCP && (input_flags & PTM_CHECK_HCP)) + flags |= PTM_CHECK_HCP; + if (num_nbrs >= PTM_NUM_NBRS_ICO && (input_flags & PTM_CHECK_ICO)) + flags |= PTM_CHECK_ICO; + if (num_nbrs >= PTM_NUM_NBRS_BCC && (input_flags & PTM_CHECK_BCC)) + flags |= PTM_CHECK_BCC; + if (num_nbrs >= PTM_NUM_NBRS_DCUB && (input_flags & PTM_CHECK_DCUB)) + flags |= PTM_CHECK_DCUB; + if (num_nbrs >= PTM_NUM_NBRS_DHEX && (input_flags & PTM_CHECK_DHEX)) + flags |= PTM_CHECK_DHEX; + + // now run PTM + int8_t mapping[MAX_NEIGHBORS + 1]; + int32_t type, alloy_type; + double scale, rmsd, interatomic_distance, lattice_constant; + double q[4], F[9], F_res[3], U[9], P[9]; + ptm_index(local_handle, flags, num_nbrs + 1, nbr, NULL, true, &type, + &alloy_type, &scale, &rmsd, q, F, F_res, U, P, mapping, + &interatomic_distance, &lattice_constant); + + if (rmsd > rmsd_threshold) { + type = PTM_MATCH_NONE; + } + + // printf("%d type=%d rmsd=%f\n", i, type, rmsd); + + if (type == PTM_MATCH_NONE) + type = OTHER; + + output[i][0] = type; + output[i][1] = rmsd; + output[i][2] = interatomic_distance; + output[i][3] = q[0]; + output[i][4] = q[1]; + output[i][5] = q[2]; + output[i][6] = q[3]; + } + + // printf("finished ptm analysis\n"); + ptm_uninitialize_local(local_handle); +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based array +------------------------------------------------------------------------- */ + +double ComputePTMAtom::memory_usage() { + double bytes = nmax * NUM_COLUMNS * sizeof(double); + bytes += nmax * sizeof(double); + return bytes; +} diff --git a/src/USER-PTM/compute_ptm_atom.h b/src/USER-PTM/compute_ptm_atom.h new file mode 100644 index 0000000000..5c10e0c443 --- /dev/null +++ b/src/USER-PTM/compute_ptm_atom.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS + +ComputeStyle(ptm/atom,ComputePTMAtom) + +#else + +#ifndef LMP_COMPUTE_PTM_ATOM_H +#define LMP_COMPUTE_PTM_ATOM_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputePTMAtom : public Compute { + public: + ComputePTMAtom(class LAMMPS *, int, char **); + ~ComputePTMAtom(); + void init(); + void init_list(int, class NeighList *); + void compute_peratom(); + double memory_usage(); + + private: + int nmax; + int32_t input_flags; + double rmsd_threshold; + class NeighList *list; + double **output; +}; + +} + +#endif +#endif + diff --git a/src/USER-PTM/config.h b/src/USER-PTM/config.h new file mode 100644 index 0000000000..eba69b3373 --- /dev/null +++ b/src/USER-PTM/config.h @@ -0,0 +1,129 @@ +// Voro++, a 3D cell-based Voronoi library +// +// Author : Chris H. Rycroft (LBL / UC Berkeley) +// Email : chr@alum.mit.edu +// Date : August 30th 2011 +// +// Modified by PM Larsen for use in Polyhedral Template Matching + +/** \file config.hh + * \brief Master configuration file for setting various compile-time options. */ + +#ifndef VOROPP_CONFIG_HH +#define VOROPP_CONFIG_HH + +namespace voro { + +// These constants set the initial memory allocation for the Voronoi cell +/** The initial memory allocation for the number of vertices. */ +const int init_vertices=256; +/** The initial memory allocation for the maximum vertex order. */ +const int init_vertex_order=64; +/** The initial memory allocation for the number of regular vertices of order + * 3. */ +const int init_3_vertices=256; +/** The initial memory allocation for the number of vertices of higher order. + */ +const int init_n_vertices=8; +/** The initial buffer size for marginal cases used by the suretest class. */ +const int init_marginal=64; +/** The initial size for the delete stack. */ +const int init_delete_size=256; +/** The initial size for the auxiliary delete stack. */ +const int init_delete2_size=256; +/** The initial size for the wall pointer array. */ +const int init_wall_size=32; +/** The default initial size for the ordering class. */ +const int init_ordering_size=4096; +/** The initial size of the pre_container chunk index. */ +const int init_chunk_size=256; + +// If the initial memory is too small, the program dynamically allocates more. +// However, if the limits below are reached, then the program bails out. +/** The maximum memory allocation for the number of vertices. */ +const int max_vertices=16777216; +/** The maximum memory allocation for the maximum vertex order. */ +const int max_vertex_order=2048; +/** The maximum memory allocation for the any particular order of vertex. */ +const int max_n_vertices=16777216; +/** The maximum buffer size for marginal cases used by the suretest class. */ +const int max_marginal=16777216; +/** The maximum size for the delete stack. */ +const int max_delete_size=16777216; +/** The maximum size for the auxiliary delete stack. */ +const int max_delete2_size=16777216; +/** The maximum amount of particle memory allocated for a single region. */ +const int max_particle_memory=16777216; +/** The maximum size for the wall pointer array. */ +const int max_wall_size=2048; +/** The maximum size for the ordering class. */ +const int max_ordering_size=67108864; +/** The maximum size for the pre_container chunk index. */ +const int max_chunk_size=65536; + +/** The chunk size in the pre_container classes. */ +const int pre_container_chunk_size=1024; + +#ifndef VOROPP_VERBOSE +/** Voro++ can print a number of different status and debugging messages to + * notify the user of special behavior, and this macro sets the amount which + * are displayed. At level 0, no messages are printed. At level 1, messages + * about unusual cases during cell construction are printed, such as when the + * plane routine bails out due to floating point problems. At level 2, general + * messages about memory expansion are printed. At level 3, technical details + * about memory management are printed. */ +#define VOROPP_VERBOSE 0 +#endif + +/** If a point is within this distance of a cutting plane, then the code + * assumes that point exactly lies on the plane. */ +const double tolerance=1e-11; + +/** If a point is within this distance of a cutting plane, then the code stores + * whether this point is inside, outside, or exactly on the cutting plane in + * the marginal cases buffer, to prevent the test giving a different result on + * a subsequent evaluation due to floating point rounding errors. */ +const double tolerance2=2e-11; + +/** The square of the tolerance, used when deciding whether some squared + * quantities are large enough to be used. */ +const double tolerance_sq=tolerance*tolerance; + +/** A large number that is used in the computation. */ +const double large_number=1e30; + +/** A radius to use as a placeholder when no other information is available. */ +const double default_radius=0.5; + +/** The maximum number of shells of periodic images to test over. */ +const int max_unit_voro_shells=10; + +/** A guess for the optimal number of particles per block, used to set up the + * container grid. */ +const double optimal_particles=5.6; + +/** If this is set to 1, then the code reports any instances of particles being + * put outside of the container geometry. */ +#define VOROPP_REPORT_OUT_OF_BOUNDS 0 + +/** Voro++ returns this status code if there is a file-related error, such as + * not being able to open file. */ +#define VOROPP_FILE_ERROR 1 + +/** Voro++ returns this status code if there is a memory allocation error, if + * one of the safe memory limits is exceeded. */ +#define VOROPP_MEMORY_ERROR 2 + +/** Voro++ returns this status code if there is any type of internal error, if + * it detects that representation of the Voronoi cell is inconsistent. This + * status code will generally indicate a bug, and the developer should be + * contacted. */ +#define VOROPP_INTERNAL_ERROR 3 + +/** Voro++ returns this status code if it could not interpret the command line + * arguments passed to the command line utility. */ +#define VOROPP_CMD_LINE_ERROR 4 + +} + +#endif diff --git a/src/USER-PTM/convex_hull_incremental.cpp b/src/USER-PTM/convex_hull_incremental.cpp new file mode 100644 index 0000000000..bfe173cc02 --- /dev/null +++ b/src/USER-PTM/convex_hull_incremental.cpp @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include +#include "convex_hull_incremental.h" +#include "ptm_constants.h" + + +#define VISIBLE 1 +#define INVISIBLE 2 +#define BOTH 3 +#define TOLERANCE 1E-8 + +static double norm_squared(double* p) +{ + double x = p[0]; + double y = p[1]; + double z = p[2]; + + return x*x + y*y + z*z; +} + +static double dot_product(const double* a, const double* b) +{ + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; +} + +static void cross_product(double* a, double* b, double* c) +{ + c[0] = a[1] * b[2] - a[2] * b[1]; + c[1] = a[2] * b[0] - a[0] * b[2]; + c[2] = a[0] * b[1] - a[1] * b[0]; +} + +static void calculate_plane_normal(const double (*points)[3], int a, int b, int c, double* plane_normal) +{ + double u[3] = { points[b][0] - points[a][0], + points[b][1] - points[a][1], + points[b][2] - points[a][2] }; + + double v[3] = { points[c][0] - points[a][0], + points[c][1] - points[a][1], + points[c][2] - points[a][2] }; + + cross_product(u, v, plane_normal); + double norm = sqrt(norm_squared(plane_normal)); + plane_normal[0] /= norm; + plane_normal[1] /= norm; + plane_normal[2] /= norm; +} + +static double point_plane_distance(const double* w, const double* plane_point, const double* plane_cross) +{ + return plane_cross[0] * (plane_point[0] - w[0]) + + plane_cross[1] * (plane_point[1] - w[1]) + + plane_cross[2] * (plane_point[2] - w[2]); +} + +static bool calc_max_extent(int num_points, const double (*points)[3], int* min_index, int* max_index) +{ + for (int j=0;j<3;j++) + { + double dmin = DBL_MAX, dmax = -DBL_MAX; + int imin = 0, imax = 0; + + for (int i = 0;i dmax) + { + dmax = d; + imax = i; + } + } + + if (imin == imax) + return false; //degenerate point set + + min_index[j] = imin; + max_index[j] = imax; + } + + return true; +} + +static bool find_third_point(int num_points, const double (*points)[3], int a, int b, int* p_c) +{ + const double* x1 = points[a]; + const double* x2 = points[b]; + + double x2x1[3] = {x2[0] - x1[0], x2[1] - x1[1], x2[2] - x1[2]}; + double ns_x2x1 = norm_squared(x2x1); + + int bi = -1; + double max_dist = 0.0; + for (int i = 0;i max_dist) + { + max_dist = dist; + bi = i; + } + } + + *p_c = bi; + return max_dist > TOLERANCE; +} + +static bool find_fourth_point(int num_points, const double (*points)[3], int a, int b, int c, int* p_d) +{ + double plane_normal[3]; + calculate_plane_normal(points, a, b, c, plane_normal); + + + int bi = -1; + double max_dist = 0.0; + for (int i = 0;i max_dist) + { + max_dist = dist; + bi = i; + } + } + + *p_d = bi; + return max_dist > TOLERANCE; +} + +static int initial_simplex(int num_points, const double (*points)[3], int* initial_vertices) +{ + int min_index[3] = {0}; + int max_index[3] = {0}; + if (!calc_max_extent(num_points, points, min_index, max_index)) + return -1; + + int bi = -1; + double max_dist = 0.0; + for (int i = 0;i<3;i++) + { + int a = min_index[i], b = max_index[i]; + double delta[3] = { points[a][0] - points[b][0], + points[a][1] - points[b][1], + points[a][2] - points[b][2] }; + double dist = norm_squared(delta); + if (dist > max_dist) + { + bi = i; + max_dist = dist; + } + } + + //first two points are (a, b) + int a = min_index[bi], b = max_index[bi], c = -1, d = -1; + + if (!find_third_point(num_points, points, a, b, &c)) + return -2; + + if (!find_fourth_point(num_points, points, a, b, c, &d)) + return -3; + + initial_vertices[0] = a; + initial_vertices[1] = b; + initial_vertices[2] = c; + initial_vertices[3] = d; + return 0; +} + +static bool visible(const double* w, const double* plane_point, const double* plane_normal) +{ + return point_plane_distance(w, plane_point, plane_normal) > 0; +} + +void add_facet(const double (*points)[3], int a, int b, int c, int8_t* facet, double* plane_normal, double* barycentre) +{ + calculate_plane_normal(points, a, b, c, plane_normal); + if (visible(barycentre, points[a], plane_normal)) + { + plane_normal[0] = -plane_normal[0]; + plane_normal[1] = -plane_normal[1]; + plane_normal[2] = -plane_normal[2]; + + facet[0] = b; + facet[1] = a; + facet[2] = c; + } + else + { + facet[0] = a; + facet[1] = b; + facet[2] = c; + } +} + +static int initialize_convex_hull(int num_points, const double (*points)[3], int8_t facets[][3], double plane_normal[][3], bool* processed, int* initial_vertices, double* barycentre) +{ + memset(processed, 0, PTM_MAX_POINTS * sizeof(bool)); + memset(barycentre, 0, 3 * sizeof(double)); + int ret = initial_simplex(num_points, points, initial_vertices); + if (ret != 0) + return ret; + + for (int i = 0;i<4;i++) + { + int a = initial_vertices[i]; + processed[a] = true; + + barycentre[0] += points[a][0]; + barycentre[1] += points[a][1]; + barycentre[2] += points[a][2]; + } + barycentre[0] /= 4; + barycentre[1] /= 4; + barycentre[2] /= 4; + + add_facet(points, initial_vertices[0], initial_vertices[1], initial_vertices[2], facets[0], plane_normal[0], barycentre); + add_facet(points, initial_vertices[0], initial_vertices[1], initial_vertices[3], facets[1], plane_normal[1], barycentre); + add_facet(points, initial_vertices[0], initial_vertices[2], initial_vertices[3], facets[2], plane_normal[2], barycentre); + add_facet(points, initial_vertices[1], initial_vertices[2], initial_vertices[3], facets[3], plane_normal[3], barycentre); + return 0; +} + +int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, int8_t simplex[][3]) +{ + assert( num_points == PTM_NUM_POINTS_FCC + || num_points == PTM_NUM_POINTS_HCP + || num_points == PTM_NUM_POINTS_BCC + || num_points == PTM_NUM_POINTS_ICO + || num_points == PTM_NUM_POINTS_SC + || num_points == PTM_NUM_POINTS_DCUB + || num_points == PTM_NUM_POINTS_DHEX); + + int ret = 0; + int num_prev = ch->num_prev; + ch->num_prev = num_points; + if (!ch->ok || 0) + { + ret = initialize_convex_hull(num_points, points, ch->facets, ch->plane_normal, ch->processed, ch->initial_vertices, ch->barycentre); + if (ret != 0) + return ret; + + ch->num_facets = 4; + num_prev = 0; + } + + for (int i = num_prev;iprocessed[i]) + continue; + ch->processed[i] = true; + + int num_to_add = 0; + int8_t to_add[PTM_MAX_FACETS][3]; + int8_t edge_visible[PTM_MAX_POINTS][PTM_MAX_POINTS]; + memset(edge_visible, 0, sizeof(int8_t) * PTM_MAX_POINTS * PTM_MAX_POINTS); + for (int j = 0;jnum_facets;j++) + { + int a = ch->facets[j][0]; + int b = ch->facets[j][1]; + int c = ch->facets[j][2]; + + int u = 0, v = 0, w = 0; + + double distance = point_plane_distance(points[i], points[a], ch->plane_normal[j]); + bool vis = distance > TOLERANCE; + if (vis) + { + u = edge_visible[a][b] |= VISIBLE; + edge_visible[b][a] |= VISIBLE; + + v = edge_visible[b][c] |= VISIBLE; + edge_visible[c][b] |= VISIBLE; + + w = edge_visible[c][a] |= VISIBLE; + edge_visible[a][c] |= VISIBLE; + + memcpy(ch->facets[j], ch->facets[ch->num_facets-1], 3 * sizeof(int8_t)); + memcpy(ch->plane_normal[j], ch->plane_normal[ch->num_facets-1], 3 * sizeof(double)); + ch->num_facets--; + j--; + } + else + { + u = edge_visible[a][b] |= INVISIBLE; + edge_visible[b][a] |= INVISIBLE; + + v = edge_visible[b][c] |= INVISIBLE; + edge_visible[c][b] |= INVISIBLE; + + w = edge_visible[c][a] |= INVISIBLE; + edge_visible[a][c] |= INVISIBLE; + } + + if (u == BOTH) + { + to_add[num_to_add][0] = i; + to_add[num_to_add][1] = a; + to_add[num_to_add][2] = b; + num_to_add++; + } + + if (v == BOTH) + { + to_add[num_to_add][0] = i; + to_add[num_to_add][1] = b; + to_add[num_to_add][2] = c; + num_to_add++; + } + + if (w == BOTH) + { + to_add[num_to_add][0] = i; + to_add[num_to_add][1] = c; + to_add[num_to_add][2] = a; + num_to_add++; + } + } + + for (int j = 0;jnum_facets >= PTM_MAX_FACETS) + return -4; + + add_facet(points, to_add[j][0], to_add[j][1], to_add[j][2], ch->facets[ch->num_facets], ch->plane_normal[ch->num_facets], ch->barycentre); ch->num_facets++; + } + } + + for (int i=0;inum_facets;i++) + { + int a = ch->facets[i][0]; + int b = ch->facets[i][1]; + int c = ch->facets[i][2]; + if (a == 0 || b == 0 || c == 0) + return 1; //central atom contained in convex hull + + simplex[i][0] = a - 1; + simplex[i][1] = b - 1; + simplex[i][2] = c - 1; + } + + return ret; +} + diff --git a/src/USER-PTM/convex_hull_incremental.h b/src/USER-PTM/convex_hull_incremental.h new file mode 100644 index 0000000000..d384a0457e --- /dev/null +++ b/src/USER-PTM/convex_hull_incremental.h @@ -0,0 +1,27 @@ +#ifndef CONVEX_HULL_INCREMENTAL_H +#define CONVEX_HULL_INCREMENTAL_H + + +#include +#include +#include "ptm_constants.h" + + +typedef struct +{ + int8_t facets[PTM_MAX_FACETS][3]; + double plane_normal[PTM_MAX_FACETS][3]; + bool processed[PTM_MAX_POINTS]; + int initial_vertices[4]; + double barycentre[3]; + int num_facets; + int num_prev; + bool ok; + +} convexhull_t; + +void add_facet(const double (*points)[3], int a, int b, int c, int8_t* facet, double* plane_normal, double* barycentre); +int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, int8_t simplex[][3]); + +#endif + diff --git a/src/USER-PTM/deformation_gradient.cpp b/src/USER-PTM/deformation_gradient.cpp new file mode 100644 index 0000000000..9a86dff6a3 --- /dev/null +++ b/src/USER-PTM/deformation_gradient.cpp @@ -0,0 +1,37 @@ +#include "deformation_gradient.h" + + +void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res) +{ + for (int i = 0;i<3;i++) + { + for (int j = 0;j<3;j++) + { + double acc = 0.0; + for (int k = 0;k +#include "ptm_constants.h" + +void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res); + +//sc +#define k_sc 0.5 +const double penrose_sc[PTM_NUM_POINTS_SC][3] = { + {0, 0, 0}, + {0, 0, -k_sc}, + {0, 0, k_sc}, + {0, -k_sc, 0}, + {0, k_sc, 0}, + {-k_sc, 0, 0}, + {k_sc, 0, 0}, + }; + +//fcc +#define k_fcc 0.17677669529663678216 +const double penrose_fcc[PTM_NUM_POINTS_FCC][3] = { + {0, 0, 0}, + {0, k_fcc, k_fcc}, + {0, -k_fcc, -k_fcc}, + {0, k_fcc, -k_fcc}, + {0, -k_fcc, k_fcc}, + {k_fcc, 0, k_fcc}, + {-k_fcc, 0, -k_fcc}, + {k_fcc, 0, -k_fcc}, + {-k_fcc, 0, k_fcc}, + {k_fcc, k_fcc, -0}, + {-k_fcc, -k_fcc, 0}, + {k_fcc, -k_fcc, 0}, + {-k_fcc, k_fcc, -0}, + }; + +//hcp +#define k_hcp 0.17677669529663678216 +const double penrose_hcp[PTM_NUM_POINTS_HCP][3] = { + {0, 0, 0}, + {k_hcp, 0, k_hcp}, + {-k_hcp/3, -4*k_hcp/3, -k_hcp/3}, + {k_hcp, k_hcp, 0}, + {-k_hcp/3, -k_hcp/3, -4*k_hcp/3}, + {0, k_hcp, k_hcp}, + {-4*k_hcp/3, -k_hcp/3, -k_hcp/3}, + {-k_hcp, k_hcp, -0}, + {0, k_hcp, -k_hcp}, + {k_hcp, 0, -k_hcp}, + {k_hcp, -k_hcp, 0}, + {-k_hcp, 0, k_hcp}, + {0, -k_hcp, k_hcp}, + }; + +//ico +#define k_ico 0.13143277802974323576 +#define phi 1.61803398874989490253 +//((1.0 + sqrt(5)) / 2) +const double penrose_ico[PTM_NUM_POINTS_ICO][3] = { + {0, 0, 0}, + {0, k_ico, phi*k_ico}, + {0, -k_ico, -phi*k_ico}, + {0, k_ico, -phi*k_ico}, + {0, -k_ico, phi*k_ico}, + {-k_ico, -phi*k_ico, -0}, + {k_ico, phi*k_ico, 0}, + {k_ico, -phi*k_ico, 0}, + {-k_ico, phi*k_ico, -0}, + {-phi*k_ico, 0, -k_ico}, + {phi*k_ico, 0, k_ico}, + {phi*k_ico, 0, -k_ico}, + {-phi*k_ico, 0, k_ico}, + }; + +//bcc +#define k_bcc 0.11543038598460284017 +const double penrose_bcc[PTM_NUM_POINTS_BCC][3] = { + {0, 0, 0}, + {-k_bcc, -k_bcc, -k_bcc}, + {k_bcc, k_bcc, k_bcc}, + {k_bcc, -k_bcc, -k_bcc}, + {-k_bcc, k_bcc, k_bcc}, + {-k_bcc, k_bcc, -k_bcc}, + {k_bcc, -k_bcc, k_bcc}, + {-k_bcc, -k_bcc, k_bcc}, + {k_bcc, k_bcc, -k_bcc}, + {0, 0, -2*k_bcc}, + {0, 0, 2*k_bcc}, + {0, -2*k_bcc, 0}, + {0, 2*k_bcc, 0}, + {-2*k_bcc, 0, 0}, + {2*k_bcc, 0, -0}, + }; + +//dcub +#define kdcub 0.07095369570691034689 +const double penrose_dcub[PTM_NUM_POINTS_DCUB][3] = { + { 0, 0, 0 }, + { -kdcub, kdcub, kdcub }, + { -kdcub, -kdcub, -kdcub }, + { kdcub, -kdcub, kdcub }, + { kdcub, kdcub, -kdcub }, + { -2 * kdcub, 0, 2 * kdcub }, + { -2 * kdcub, 2 * kdcub, 0 }, + { 0, 2 * kdcub, 2 * kdcub }, + { -2 * kdcub, -2 * kdcub, 0 }, + { -2 * kdcub, 0, -2 * kdcub }, + { 0, -2 * kdcub, -2 * kdcub }, + { 0, -2 * kdcub, 2 * kdcub }, + { 2 * kdcub, -2 * kdcub, 0 }, + { 2 * kdcub, 0, 2 * kdcub }, + { 0, 2 * kdcub, -2 * kdcub }, + { 2 * kdcub, 0, -2 * kdcub }, + { 2 * kdcub, 2 * kdcub, 0 }, + }; + + +#define kdhex 0.04730246380471011397 +const double penrose_dhex[PTM_NUM_POINTS_DHEX][3] = { + { 0, 0, 0 }, + { -kdcub, -kdcub, -kdcub }, + { kdcub, -kdcub, kdcub }, + { -kdcub, kdcub, kdcub }, + { kdcub, kdcub, -kdcub }, + { -kdhex, -4 * kdhex, -kdhex }, + { -4 * kdhex, -kdhex, -kdhex }, + { -kdhex, -kdhex, -4 * kdhex }, + { 2 * kdcub, 0, 2 * kdcub }, + { 2 * kdcub, -2 * kdcub, 0 }, + { 0, -2 * kdcub, 2 * kdcub }, + { 0, 2 * kdcub, 2 * kdcub }, + { -2 * kdcub, 2 * kdcub, 0 }, + { -2 * kdcub, 0, 2 * kdcub }, + { 2 * kdcub, 2 * kdcub, 0 }, + { 0, 2 * kdcub, -2 * kdcub }, + { 2 * kdcub, 0, -2 * kdcub }, + }; +#endif + + diff --git a/src/USER-PTM/fundamental_mappings.h b/src/USER-PTM/fundamental_mappings.h new file mode 100644 index 0000000000..9030d3a2b2 --- /dev/null +++ b/src/USER-PTM/fundamental_mappings.h @@ -0,0 +1,180 @@ +#ifndef FUNDAMENTAL_MAPPINGS_H +#define FUNDAMENTAL_MAPPINGS_H + +#include + +#define NUM_CUBIC_MAPPINGS 24 +#define NUM_ICO_MAPPINGS 60 +#define NUM_HEX_MAPPINGS 6 +#define NUM_DCUB_MAPPINGS 12 +#define NUM_DHEX_MAPPINGS 3 + +const int8_t mapping_sc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6}, + {0, 2, 1, 4, 3, 5, 6}, + {0, 2, 1, 3, 4, 6, 5}, + {0, 1, 2, 4, 3, 6, 5}, + {0, 3, 4, 5, 6, 1, 2}, + {0, 5, 6, 2, 1, 4, 3}, + {0, 6, 5, 1, 2, 4, 3}, + {0, 4, 3, 5, 6, 2, 1}, + {0, 5, 6, 1, 2, 3, 4}, + {0, 4, 3, 6, 5, 1, 2}, + {0, 3, 4, 6, 5, 2, 1}, + {0, 6, 5, 2, 1, 3, 4}, + {0, 3, 4, 2, 1, 5, 6}, + {0, 6, 5, 3, 4, 1, 2}, + {0, 1, 2, 5, 6, 4, 3}, + {0, 4, 3, 1, 2, 5, 6}, + {0, 5, 6, 3, 4, 2, 1}, + {0, 1, 2, 6, 5, 3, 4}, + {0, 2, 1, 5, 6, 3, 4}, + {0, 5, 6, 4, 3, 1, 2}, + {0, 3, 4, 1, 2, 6, 5}, + {0, 2, 1, 6, 5, 4, 3}, + {0, 6, 5, 4, 3, 2, 1}, + {0, 4, 3, 2, 1, 6, 5} }; + +const int8_t mapping_fcc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + {0, 2, 1, 4, 3, 7, 8, 5, 6, 11, 12, 9, 10}, + {0, 3, 4, 1, 2, 6, 5, 8, 7, 12, 11, 10, 9}, + {0, 4, 3, 2, 1, 8, 7, 6, 5, 10, 9, 12, 11}, + {0, 9, 10, 11, 12, 1, 2, 4, 3, 5, 6, 8, 7}, + {0, 7, 8, 6, 5, 11, 12, 10, 9, 2, 1, 4, 3}, + {0, 8, 7, 5, 6, 10, 9, 11, 12, 4, 3, 2, 1}, + {0, 11, 12, 9, 10, 2, 1, 3, 4, 7, 8, 6, 5}, + {0, 5, 6, 8, 7, 9, 10, 12, 11, 1, 2, 3, 4}, + {0, 10, 9, 12, 11, 4, 3, 1, 2, 8, 7, 5, 6}, + {0, 12, 11, 10, 9, 3, 4, 2, 1, 6, 5, 7, 8}, + {0, 6, 5, 7, 8, 12, 11, 9, 10, 3, 4, 1, 2}, + {0, 3, 4, 2, 1, 9, 10, 11, 12, 7, 8, 5, 6}, + {0, 12, 11, 9, 10, 8, 7, 5, 6, 1, 2, 4, 3}, + {0, 5, 6, 7, 8, 4, 3, 2, 1, 11, 12, 10, 9}, + {0, 4, 3, 1, 2, 11, 12, 9, 10, 5, 6, 7, 8}, + {0, 9, 10, 12, 11, 7, 8, 6, 5, 3, 4, 2, 1}, + {0, 8, 7, 6, 5, 1, 2, 3, 4, 12, 11, 9, 10}, + {0, 7, 8, 5, 6, 3, 4, 1, 2, 9, 10, 12, 11}, + {0, 11, 12, 10, 9, 5, 6, 8, 7, 4, 3, 1, 2}, + {0, 1, 2, 4, 3, 12, 11, 10, 9, 8, 7, 6, 5}, + {0, 6, 5, 8, 7, 2, 1, 4, 3, 10, 9, 11, 12}, + {0, 10, 9, 11, 12, 6, 5, 7, 8, 2, 1, 3, 4}, + {0, 2, 1, 3, 4, 10, 9, 12, 11, 6, 5, 8, 7} }; + +const int8_t mapping_bcc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {0, 4, 3, 2, 1, 7, 8, 5, 6, 10, 9, 12, 11, 13, 14}, + {0, 6, 5, 7, 8, 2, 1, 3, 4, 10, 9, 11, 12, 14, 13}, + {0, 8, 7, 5, 6, 3, 4, 2, 1, 9, 10, 12, 11, 14, 13}, + {0, 1, 2, 7, 8, 3, 4, 5, 6, 11, 12, 13, 14, 9, 10}, + {0, 4, 3, 7, 8, 5, 6, 2, 1, 13, 14, 10, 9, 12, 11}, + {0, 8, 7, 3, 4, 2, 1, 5, 6, 14, 13, 9, 10, 12, 11}, + {0, 4, 3, 5, 6, 2, 1, 7, 8, 12, 11, 13, 14, 10, 9}, + {0, 1, 2, 5, 6, 7, 8, 3, 4, 13, 14, 9, 10, 11, 12}, + {0, 8, 7, 2, 1, 5, 6, 3, 4, 12, 11, 14, 13, 9, 10}, + {0, 6, 5, 3, 4, 7, 8, 2, 1, 11, 12, 14, 13, 10, 9}, + {0, 6, 5, 2, 1, 3, 4, 7, 8, 14, 13, 10, 9, 11, 12}, + {0, 7, 8, 6, 5, 1, 2, 4, 3, 11, 12, 10, 9, 13, 14}, + {0, 3, 4, 6, 5, 8, 7, 1, 2, 14, 13, 11, 12, 9, 10}, + {0, 5, 6, 1, 2, 8, 7, 4, 3, 9, 10, 13, 14, 12, 11}, + {0, 5, 6, 8, 7, 4, 3, 1, 2, 12, 11, 9, 10, 13, 14}, + {0, 7, 8, 1, 2, 4, 3, 6, 5, 13, 14, 11, 12, 10, 9}, + {0, 3, 4, 8, 7, 1, 2, 6, 5, 9, 10, 14, 13, 11, 12}, + {0, 7, 8, 4, 3, 6, 5, 1, 2, 10, 9, 13, 14, 11, 12}, + {0, 5, 6, 4, 3, 1, 2, 8, 7, 13, 14, 12, 11, 9, 10}, + {0, 3, 4, 1, 2, 6, 5, 8, 7, 11, 12, 9, 10, 14, 13}, + {0, 2, 1, 6, 5, 4, 3, 8, 7, 10, 9, 14, 13, 12, 11}, + {0, 2, 1, 8, 7, 6, 5, 4, 3, 14, 13, 12, 11, 10, 9}, + {0, 2, 1, 4, 3, 8, 7, 6, 5, 12, 11, 10, 9, 14, 13} }; + +const int8_t mapping_ico[NUM_ICO_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + {0, 10, 9, 8, 7, 5, 6, 2, 1, 12, 11, 3, 4}, + {0, 1, 2, 9, 10, 7, 8, 11, 12, 5, 6, 3, 4}, + {0, 4, 3, 8, 7, 2, 1, 11, 12, 9, 10, 6, 5}, + {0, 6, 5, 9, 10, 4, 3, 7, 8, 12, 11, 2, 1}, + {0, 12, 11, 3, 4, 7, 8, 10, 9, 2, 1, 6, 5}, + {0, 4, 3, 6, 5, 9, 10, 2, 1, 8, 7, 11, 12}, + {0, 8, 7, 2, 1, 4, 3, 10, 9, 5, 6, 11, 12}, + {0, 10, 9, 3, 4, 12, 11, 5, 6, 8, 7, 2, 1}, + {0, 12, 11, 6, 5, 2, 1, 7, 8, 3, 4, 10, 9}, + {0, 1, 2, 11, 12, 9, 10, 5, 6, 3, 4, 7, 8}, + {0, 8, 7, 11, 12, 5, 6, 4, 3, 2, 1, 10, 9}, + {0, 6, 5, 2, 1, 12, 11, 4, 3, 9, 10, 7, 8}, + {0, 3, 4, 5, 6, 1, 2, 10, 9, 12, 11, 7, 8}, + {0, 3, 4, 7, 8, 12, 11, 1, 2, 5, 6, 10, 9}, + {0, 6, 5, 7, 8, 9, 10, 12, 11, 2, 1, 4, 3}, + {0, 9, 10, 11, 12, 4, 3, 1, 2, 7, 8, 6, 5}, + {0, 11, 12, 9, 10, 1, 2, 4, 3, 8, 7, 5, 6}, + {0, 8, 7, 5, 6, 10, 9, 11, 12, 4, 3, 2, 1}, + {0, 10, 9, 2, 1, 8, 7, 12, 11, 3, 4, 5, 6}, + {0, 12, 11, 2, 1, 10, 9, 6, 5, 7, 8, 3, 4}, + {0, 9, 10, 6, 5, 7, 8, 4, 3, 11, 12, 1, 2}, + {0, 8, 7, 10, 9, 2, 1, 5, 6, 11, 12, 4, 3}, + {0, 6, 5, 12, 11, 7, 8, 2, 1, 4, 3, 9, 10}, + {0, 11, 12, 8, 7, 4, 3, 5, 6, 1, 2, 9, 10}, + {0, 4, 3, 11, 12, 8, 7, 9, 10, 6, 5, 2, 1}, + {0, 4, 3, 9, 10, 11, 12, 6, 5, 2, 1, 8, 7}, + {0, 12, 11, 10, 9, 3, 4, 2, 1, 6, 5, 7, 8}, + {0, 5, 6, 8, 7, 11, 12, 10, 9, 3, 4, 1, 2}, + {0, 7, 8, 6, 5, 12, 11, 9, 10, 1, 2, 3, 4}, + {0, 10, 9, 12, 11, 2, 1, 3, 4, 5, 6, 8, 7}, + {0, 7, 8, 1, 2, 9, 10, 3, 4, 12, 11, 6, 5}, + {0, 5, 6, 1, 2, 3, 4, 11, 12, 8, 7, 10, 9}, + {0, 7, 8, 12, 11, 3, 4, 6, 5, 9, 10, 1, 2}, + {0, 1, 2, 5, 6, 11, 12, 3, 4, 7, 8, 9, 10}, + {0, 11, 12, 1, 2, 5, 6, 9, 10, 4, 3, 8, 7}, + {0, 5, 6, 3, 4, 10, 9, 1, 2, 11, 12, 8, 7}, + {0, 5, 6, 10, 9, 8, 7, 3, 4, 1, 2, 11, 12}, + {0, 3, 4, 12, 11, 10, 9, 7, 8, 1, 2, 5, 6}, + {0, 9, 10, 7, 8, 1, 2, 6, 5, 4, 3, 11, 12}, + {0, 9, 10, 1, 2, 11, 12, 7, 8, 6, 5, 4, 3}, + {0, 7, 8, 3, 4, 1, 2, 12, 11, 6, 5, 9, 10}, + {0, 11, 12, 5, 6, 8, 7, 1, 2, 9, 10, 4, 3}, + {0, 1, 2, 7, 8, 3, 4, 9, 10, 11, 12, 5, 6}, + {0, 3, 4, 10, 9, 5, 6, 12, 11, 7, 8, 1, 2}, + {0, 2, 1, 4, 3, 8, 7, 6, 5, 12, 11, 10, 9}, + {0, 2, 1, 12, 11, 6, 5, 10, 9, 8, 7, 4, 3}, + {0, 9, 10, 4, 3, 6, 5, 11, 12, 1, 2, 7, 8}, + {0, 11, 12, 4, 3, 9, 10, 8, 7, 5, 6, 1, 2}, + {0, 2, 1, 10, 9, 12, 11, 8, 7, 4, 3, 6, 5}, + {0, 5, 6, 11, 12, 1, 2, 8, 7, 10, 9, 3, 4}, + {0, 10, 9, 5, 6, 3, 4, 8, 7, 2, 1, 12, 11}, + {0, 12, 11, 7, 8, 6, 5, 3, 4, 10, 9, 2, 1}, + {0, 7, 8, 9, 10, 6, 5, 1, 2, 3, 4, 12, 11}, + {0, 2, 1, 8, 7, 10, 9, 4, 3, 6, 5, 12, 11}, + {0, 8, 7, 4, 3, 11, 12, 2, 1, 10, 9, 5, 6}, + {0, 6, 5, 4, 3, 2, 1, 9, 10, 7, 8, 12, 11}, + {0, 2, 1, 6, 5, 4, 3, 12, 11, 10, 9, 8, 7}, + {0, 3, 4, 1, 2, 7, 8, 5, 6, 10, 9, 12, 11}, + {0, 4, 3, 2, 1, 6, 5, 8, 7, 11, 12, 9, 10} }; + +const int8_t mapping_hcp[NUM_HEX_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + {0, 5, 6, 1, 2, 3, 4, 9, 10, 12, 11, 8, 7}, + {0, 3, 4, 5, 6, 1, 2, 12, 11, 7, 8, 10, 9}, + {0, 4, 3, 2, 1, 6, 5, 11, 12, 10, 9, 7, 8}, + {0, 2, 1, 6, 5, 4, 3, 8, 7, 11, 12, 9, 10}, + {0, 6, 5, 4, 3, 2, 1, 10, 9, 8, 7, 12, 11} }; + +const int8_t mapping_dcub[NUM_DCUB_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + {0, 2, 1, 4, 3, 9, 8, 10, 6, 5, 7, 14, 16, 15, 11, 13, 12}, + {0, 4, 3, 2, 1, 15, 16, 14, 12, 13, 11, 10, 8, 9, 7, 5, 6}, + {0, 3, 4, 1, 2, 13, 12, 11, 16, 15, 14, 7, 6, 5, 10, 9, 8}, + {0, 4, 2, 1, 3, 14, 15, 16, 9, 10, 8, 6, 5, 7, 12, 11, 13}, + {0, 4, 1, 3, 2, 16, 14, 15, 7, 6, 5, 13, 11, 12, 9, 8, 10}, + {0, 1, 4, 2, 3, 6, 7, 5, 14, 16, 15, 9, 10, 8, 13, 12, 11}, + {0, 3, 1, 2, 4, 11, 13, 12, 5, 7, 6, 8, 9, 10, 16, 14, 15}, + {0, 3, 2, 4, 1, 12, 11, 13, 10, 8, 9, 15, 14, 16, 5, 6, 7}, + {0, 2, 4, 3, 1, 10, 9, 8, 15, 14, 16, 12, 13, 11, 6, 7, 5}, + {0, 1, 3, 4, 2, 7, 5, 6, 13, 11, 12, 16, 15, 14, 8, 10, 9}, + {0, 2, 3, 1, 4, 8, 10, 9, 11, 12, 13, 5, 7, 6, 15, 16, 14} }; + +const int8_t mapping_dhex[NUM_DHEX_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + {0, 1, 3, 4, 2, 6, 7, 5, 11, 13, 12, 14, 16, 15, 8, 9, 10}, + {0, 1, 4, 2, 3, 7, 5, 6, 14, 15, 16, 8, 10, 9, 11, 13, 12} }; + +#endif + diff --git a/src/USER-PTM/graph_data.cpp b/src/USER-PTM/graph_data.cpp new file mode 100644 index 0000000000..aea2e59eac --- /dev/null +++ b/src/USER-PTM/graph_data.cpp @@ -0,0 +1,2059 @@ +#include "graph_data.h" + + +int8_t automorphisms[65][17] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 4, 3, 10, 9, 5, 6, 12, 11, 8, 7, 1, 2, -1, -1, -1, -1}, + { 0, 5, 6, 11, 12, 8, 7, 2, 1, 4, 3, 10, 9, -1, -1, -1, -1}, + { 0, 8, 7, 1, 2, 4, 3, 9, 10, 5, 6, 11, 12, -1, -1, -1, -1}, + { 0, 8, 7, 10, 9, 1, 2, 6, 5, 12, 11, 3, 4, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 12, 3, 2, 7, 10, 8, 4, 6, 11, 5, 9, 1, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 4, 11, 8, 1, 9, 12, 10, 3, 5, 7, 2, 6, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 2, 1, 6, 5, 4, 3, 9, 8, 7, 11, 10, 12, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 1, 7, 10, 11, 9, 6, 4, 2, 12, 5, 8, 3, -1, -1, -1, -1}, + { 0, 1, 11, 9, 2, 3, 6, 8, 4, 10, 12, 7, 5, -1, -1, -1, -1}, + { 0, 3, 6, 1, 11, 9, 2, 10, 12, 5, 7, 4, 8, -1, -1, -1, -1}, + { 0, 3, 11, 9, 12, 8, 2, 4, 10, 1, 5, 6, 7, -1, -1, -1, -1}, + { 0, 8, 2, 3, 11, 9, 12, 1, 5, 7, 6, 10, 4, -1, -1, -1, -1}, + { 0, 9, 2, 3, 6, 1, 11, 5, 7, 8, 4, 12, 10, -1, -1, -1, -1}, + { 0, 9, 6, 1, 7, 10, 11, 12, 5, 3, 8, 2, 4, -1, -1, -1, -1}, + { 0, 9, 12, 8, 2, 3, 11, 7, 6, 4, 10, 5, 1, -1, -1, -1, -1}, + { 0, 10, 11, 9, 6, 1, 7, 3, 8, 4, 2, 5, 12, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 3, 2, 8, 6, 5, 12, 11, 7, 4, 9, 1, 10, -1, -1, -1, -1}, + { 0, 3, 11, 10, 6, 9, 7, 4, 2, 12, 1, 8, 5, -1, -1, -1, -1}, + { 0, 3, 12, 9, 6, 8, 11, 7, 4, 2, 10, 5, 1, -1, -1, -1, -1}, + { 0, 5, 12, 3, 2, 8, 6, 4, 9, 10, 1, 7, 11, -1, -1, -1, -1}, + { 0, 8, 6, 5, 12, 3, 2, 10, 1, 11, 7, 9, 4, -1, -1, -1, -1}, + { 0, 8, 11, 3, 12, 9, 6, 2, 10, 1, 5, 4, 7, -1, -1, -1, -1}, + { 0, 9, 6, 8, 11, 3, 12, 1, 5, 7, 4, 10, 2, -1, -1, -1, -1}, + { 0, 9, 7, 3, 11, 10, 6, 12, 1, 5, 8, 2, 4, -1, -1, -1, -1}, + { 0, 10, 6, 9, 7, 3, 11, 5, 8, 4, 2, 1, 12, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 3, 4, 6, 5, 2, 1, 9, 10, 14, 13, 11, 12, 8, 7, -1, -1}, + { 0, 4, 3, 1, 2, 5, 6, 10, 9, 13, 14, 7, 8, 12, 11, -1, -1}, + { 0, 6, 5, 1, 2, 4, 3, 14, 13, 7, 8, 11, 12, 10, 9, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 12, 11, 10, 9, 13, 14, 8, 7, 4, 3, 2, 1, 5, 6, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 9, 10, 13, 14, 11, 12, 8, 7, 1, 2, 5, 6, 3, 4, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 6, 5, 4, 3, 2, 1, 11, 12, 10, 9, 7, 8, 14, 13, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 12, 11, 10, 9, 13, 14, 8, 7, 4, 3, 2, 1, 5, 6, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 9, 10, 13, 14, 11, 12, 8, 7, 1, 2, 5, 6, 3, 4, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 3, 10, 14, 5, 9, 7, 13, 2, 8, 4, 11, 12, 1, 6, -1, -1}, + { 0, 13, 8, 1, 10, 4, 14, 6, 9, 5, 2, 11, 12, 7, 3, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 11, 12, 14, 13, 9, 10, 7, 8, 3, 4, 6, 5, 1, 2, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 13, 14, 11, 12, 5, 6, 10, 9, 1, 2, 7, 8, 4, 3, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 4, 3, 2, 1, 15, 14, 16, 13, 12, 11, 10, 9, 8, 6, 5, 7}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 4, 1, 3, 2, 15, 14, 16, 5, 7, 6, 13, 11, 12, 10, 8, 9}, + { 0, 4, 2, 1, 3, 16, 15, 14, 10, 8, 9, 5, 6, 7, 13, 12, 11}, + { 0, 4, 3, 2, 1, 14, 16, 15, 13, 12, 11, 10, 9, 8, 5, 7, 6}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 3, 4, 1, 2, 12, 13, 11, 16, 14, 15, 7, 5, 6, 9, 10, 8}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 4, 1, 3, 2, 16, 15, 14, 6, 5, 7, 13, 11, 12, 10, 8, 9}, + { 0, 4, 2, 1, 3, 14, 16, 15, 10, 8, 9, 6, 7, 5, 13, 12, 11}, + { 0, 4, 3, 2, 1, 15, 14, 16, 13, 12, 11, 10, 9, 8, 6, 5, 7}, +}; + +graph_t graphs_sc[NUM_SC_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,4},{1,3,5},{0,3,4},{0,3,5},{1,2,5},{1,2,4},{0,2,4},{0,2,5}}}, + +}; + +graph_t graphs_ico[NUM_ICO_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,5,9},{1,2,8},{0,5,7},{2,7,8},{2,5,7},{1,4,8},{1,2,10},{5,9,10},{2,5,10},{4,8,11},{7,8,11},{0,7,11},{0,3,9},{0,3,11},{3,4,11},{3,6,9},{3,4,6},{6,9,10},{1,4,6},{1,6,10}}}, + +}; + +graph_t graphs_fcc[NUM_FCC_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{1,3,10},{1,3,9},{4,6,10},{4,6,8}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{3,9,10},{1,9,10},{6,8,10},{4,8,10}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{4,6,10},{4,6,8}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{3,9,10},{1,9,10},{4,6,10},{4,6,8}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{7,9,11},{5,9,11},{1,2,6},{1,2,5},{3,9,10},{1,9,10},{4,6,10},{4,6,8}}}, + +{7, +0, +1, +5, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{7,9,11},{5,9,11},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, + +}; + +graph_t graphs_hcp[NUM_HCP_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{6, +0, +6, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{7, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, + +{9, +0, +8, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{12, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{13, +0, +10, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{5,6,7},{3,5,7},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{14, +0, +12, +10, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{5,6,7},{3,5,7},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{15, +0, +22, +10, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{5,10,11},{1,5,11},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +}; + +graph_t graphs_bcc[NUM_BCC_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{7, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{9, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{12, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{13, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{14, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{15, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{16, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{17, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{18, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{19, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{20, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{21, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{22, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{23, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{24, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{25, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{26, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{27, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{28, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{29, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{30, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{31, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{32, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{33, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{34, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{35, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{36, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{37, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{38, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{39, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{40, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{41, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{42, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{43, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{44, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{45, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{46, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{47, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{48, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{49, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{50, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{51, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{52, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{53, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{54, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{55, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{56, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{57, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{58, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{59, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{60, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{61, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{62, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{63, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{64, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{65, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{66, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{67, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{68, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{69, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{70, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{71, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{72, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{73, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{74, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{75, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{76, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{77, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{78, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{79, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{80, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{81, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{82, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{83, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{84, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{85, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{86, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{87, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{88, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{89, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{90, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{91, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{92, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{93, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{94, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{95, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{96, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{97, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{98, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{99, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{100, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{101, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{102, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{103, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{104, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{105, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{106, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{107, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{108, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{109, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{110, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{111, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{112, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{113, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{114, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{115, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{116, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{117, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{118, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{119, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{120, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{121, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{122, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{123, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{124, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{125, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{126, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{127, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{128, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{129, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{130, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{131, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{132, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{133, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{134, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{135, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{136, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{137, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{138, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{139, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{140, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{141, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{142, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{143, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{144, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{145, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{146, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{147, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{148, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{149, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{150, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{151, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{152, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{153, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{154, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{155, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{156, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{157, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{158, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{159, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{160, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{161, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{162, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{163, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{164, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{165, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{166, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{167, +0, +32, +4, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{168, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{169, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{170, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{171, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{172, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{173, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{174, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{175, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{176, +0, +36, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{177, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{178, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{179, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{180, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{181, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{182, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{183, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{184, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{185, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{186, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{187, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{188, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{189, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{190, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{191, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{192, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{193, +0, +38, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{194, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{195, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{196, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{197, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{198, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{199, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{200, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{201, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{202, +0, +40, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{203, +0, +42, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{204, +0, +44, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{205, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{206, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{207, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{208, +0, +46, +3, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{209, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{210, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{211, +0, +49, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{212, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{213, +0, +51, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{214, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{215, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{216, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{217, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,11},{1,3,9},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +}; + +graph_t graphs_dcub[NUM_DCUB_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{12,14,15},{11,12,14}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, + +{7, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, + +{9, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{4,10,12},{4,6,12},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{4,7,8},{4,5,8},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{12,14,15},{11,12,14}}}, + +}; + +graph_t graphs_dhex[NUM_DHEX_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{7,13,15},{7,8,15}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{7, +0, +53, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{9, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{12, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{13, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{14, +0, +55, +4, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{15, +0, +59, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{16, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{17, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{18, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{19, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{20, +0, +61, +4, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{21, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{22, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{23, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +}; + diff --git a/src/USER-PTM/graph_data.h b/src/USER-PTM/graph_data.h new file mode 100644 index 0000000000..3a8a5c7ae7 --- /dev/null +++ b/src/USER-PTM/graph_data.h @@ -0,0 +1,37 @@ +#ifndef GRAPH_DATA_H +#define GRAPH_DATA_H + +#include +#include "ptm_constants.h" + + +typedef struct +{ + int id; + uint64_t hash; + int automorphism_index; + int num_automorphisms; + int8_t canonical_labelling[PTM_MAX_POINTS]; + int8_t facets[PTM_MAX_FACETS][3]; +} graph_t; + +#define NUM_SC_GRAPHS 1 +#define NUM_ICO_GRAPHS 1 +#define NUM_FCC_GRAPHS 8 +#define NUM_HCP_GRAPHS 16 +#define NUM_BCC_GRAPHS 218 +#define NUM_DCUB_GRAPHS 12 +#define NUM_DHEX_GRAPHS 24 + +extern int8_t automorphisms[][PTM_MAX_POINTS]; + +extern graph_t graphs_sc[NUM_SC_GRAPHS]; +extern graph_t graphs_fcc[NUM_FCC_GRAPHS]; +extern graph_t graphs_hcp[NUM_HCP_GRAPHS]; +extern graph_t graphs_ico[NUM_ICO_GRAPHS]; +extern graph_t graphs_bcc[NUM_BCC_GRAPHS]; +extern graph_t graphs_dcub[NUM_DCUB_GRAPHS]; +extern graph_t graphs_dhex[NUM_DHEX_GRAPHS]; + +#endif + diff --git a/src/USER-PTM/graph_tools.cpp b/src/USER-PTM/graph_tools.cpp new file mode 100644 index 0000000000..864e921b51 --- /dev/null +++ b/src/USER-PTM/graph_tools.cpp @@ -0,0 +1,52 @@ +#include +#include +#include "graph_tools.h" +#include "ptm_constants.h" + + +bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]) +{ + memset(common, -1, sizeof(int8_t) * PTM_MAX_NBRS * PTM_MAX_NBRS); + + for (int i = 0;i +#include "ptm_constants.h" + +bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]); +int graph_degree(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree); + +#endif + diff --git a/src/USER-PTM/index_ptm.cpp b/src/USER-PTM/index_ptm.cpp new file mode 100644 index 0000000000..2683323ac5 --- /dev/null +++ b/src/USER-PTM/index_ptm.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include +#include "convex_hull_incremental.h" +#include "graph_data.h" +#include "deformation_gradient.h" +#include "alloy_types.h" +#include "neighbour_ordering.h" +#include "normalize_vertices.h" +#include "quat.h" +#include "polar.h" +#include "initialize_data.h" +#include "structure_matcher.h" +#include "ptm_functions.h" +#include "ptm_constants.h" + + +//todo: verify that c == norm(template[1]) +static double calculate_interatomic_distance(int type, double scale) +{ + assert(type >= 1 && type <= 7); + double c[8] = {0, 1, 1, (7. - 3.5 * sqrt(3)), 1, 1, sqrt(3) * 4. / (6 * sqrt(2) + sqrt(3)), sqrt(3) * 4. / (6 * sqrt(2) + sqrt(3))}; + return c[type] / scale; +} + +static double calculate_lattice_constant(int type, double interatomic_distance) +{ + assert(type >= 1 && type <= 7); + double c[8] = {0, 2 / sqrt(2), 2 / sqrt(2), 2. / sqrt(3), 2 / sqrt(2), 1, 4 / sqrt(3), 4 / sqrt(3)}; + return c[type] * interatomic_distance; +} + +static int rotate_into_fundamental_zone(int type, double* q) +{ + if (type == PTM_MATCH_SC) return rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_FCC) return rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_BCC) return rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_ICO) return rotate_quaternion_into_icosahedral_fundamental_zone(q); + if (type == PTM_MATCH_HCP) return rotate_quaternion_into_hcp_fundamental_zone(q); + if (type == PTM_MATCH_DCUB) return rotate_quaternion_into_diamond_cubic_fundamental_zone(q); + if (type == PTM_MATCH_DHEX) return rotate_quaternion_into_diamond_hexagonal_fundamental_zone(q); + return -1; +} + +static void order_points(ptm_local_handle_t local_handle, int num_points, double (*unpermuted_points)[3], int32_t* unpermuted_numbers, bool topological_ordering, + int8_t* ordering, double (*points)[3], int32_t* numbers) +{ + if (topological_ordering) + { + double normalized_points[PTM_MAX_INPUT_POINTS][3]; + normalize_vertices(num_points, unpermuted_points, normalized_points); + int ret = calculate_neighbour_ordering((void*)local_handle, num_points, (const double (*)[3])normalized_points, ordering); + if (ret != 0) + topological_ordering = false; + } + + if (!topological_ordering) + for (int i=0;iref_struct; + if (ref == NULL) + return; + + *p_type = ref->type; + if (p_alloy_type != NULL && unpermuted_numbers != NULL) + *p_alloy_type = find_alloy_type(ref, res->mapping, numbers); + + int bi = rotate_into_fundamental_zone(ref->type, res->q); + int8_t temp[PTM_MAX_POINTS]; + for (int i=0;inum_nbrs+1;i++) + temp[ref->mapping[bi][i]] = res->mapping[i]; + + memcpy(res->mapping, temp, (ref->num_nbrs+1) * sizeof(int8_t)); + + if (F != NULL && F_res != NULL) + { + double scaled_points[PTM_MAX_INPUT_POINTS][3]; + + subtract_barycentre(ref->num_nbrs + 1, points, scaled_points); + for (int i = 0;inum_nbrs + 1;i++) + { + scaled_points[i][0] *= res->scale; + scaled_points[i][1] *= res->scale; + scaled_points[i][2] *= res->scale; + } + calculate_deformation_gradient(ref->num_nbrs + 1, ref->points, res->mapping, scaled_points, ref->penrose, F, F_res); + + if (P != NULL && U != NULL) + polar_decomposition_3x3(F, false, U, P); + } + + if (mapping != NULL) + for (int i=0;inum_nbrs + 1;i++) + mapping[i] = ordering[res->mapping[i]]; + + double interatomic_distance = calculate_interatomic_distance(ref->type, res->scale); + double lattice_constant = calculate_lattice_constant(ref->type, interatomic_distance); + + if (p_interatomic_distance != NULL) + *p_interatomic_distance = interatomic_distance; + + if (p_lattice_constant != NULL) + *p_lattice_constant = lattice_constant; + + *p_rmsd = res->rmsd; + *p_scale = res->scale; + memcpy(q, res->q, 4 * sizeof(double)); +} + + +extern bool ptm_initialized; + +int ptm_index( ptm_local_handle_t local_handle, int32_t flags, + int num_points, double (*unpermuted_points)[3], int32_t* unpermuted_numbers, bool topological_ordering, + int32_t* p_type, int32_t* p_alloy_type, double* p_scale, double* p_rmsd, double* q, double* F, double* F_res, + double* U, double* P, int8_t* mapping, double* p_interatomic_distance, double* p_lattice_constant) +{ + assert(ptm_initialized); + assert(num_points <= PTM_MAX_INPUT_POINTS); + + if (flags & PTM_CHECK_SC) + assert(num_points >= PTM_NUM_POINTS_SC); + + if (flags & PTM_CHECK_BCC) + assert(num_points >= PTM_NUM_POINTS_BCC); + + if (flags & (PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO)) + assert(num_points >= PTM_NUM_POINTS_FCC); + + if (flags & (PTM_CHECK_DCUB | PTM_CHECK_DHEX)) + assert(num_points >= PTM_NUM_POINTS_DCUB); + + int ret = 0; + result_t res; + res.ref_struct = NULL; + res.rmsd = INFINITY; + + int8_t ordering[PTM_MAX_INPUT_POINTS]; + double points[PTM_MAX_POINTS][3]; + int32_t numbers[PTM_MAX_POINTS]; + + int8_t dordering[PTM_MAX_INPUT_POINTS]; + double dpoints[PTM_MAX_POINTS][3]; + int32_t dnumbers[PTM_MAX_POINTS]; + + convexhull_t ch; + double ch_points[PTM_MAX_INPUT_POINTS][3]; + + if (flags & (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC)) + { + int num_lpoints = std::min(std::min(PTM_MAX_POINTS, 20), num_points); + order_points(local_handle, num_lpoints, unpermuted_points, unpermuted_numbers, topological_ordering, ordering, points, numbers); + normalize_vertices(num_lpoints, points, ch_points); + ch.ok = false; + + if (flags & PTM_CHECK_SC) + ret = match_general(&structure_sc, ch_points, points, &ch, &res); + + if (flags & (PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO)) + ret = match_fcc_hcp_ico(ch_points, points, flags, &ch, &res); + + if (flags & PTM_CHECK_BCC) + ret = match_general(&structure_bcc, ch_points, points, &ch, &res); + } + + if (flags & (PTM_CHECK_DCUB | PTM_CHECK_DHEX)) + { + ret = calculate_diamond_neighbour_ordering(num_points, unpermuted_points, unpermuted_numbers, dordering, dpoints, dnumbers); + if (ret == 0) + { + normalize_vertices(PTM_NUM_NBRS_DCUB + 1, dpoints, ch_points); + ch.ok = false; + + ret = match_dcub_dhex(ch_points, dpoints, flags, &ch, &res); + } + } + + if (res.ref_struct != NULL && (res.ref_struct->type == PTM_MATCH_DCUB || res.ref_struct->type == PTM_MATCH_DHEX)) + { + output_data( &res, num_points, unpermuted_numbers, dpoints, dnumbers, dordering, + p_type, p_alloy_type, p_scale, p_rmsd, q, F, F_res, + U, P, mapping, p_interatomic_distance, p_lattice_constant); + } + else + { + output_data( &res, num_points, unpermuted_numbers, points, numbers, ordering, + p_type, p_alloy_type, p_scale, p_rmsd, q, F, F_res, + U, P, mapping, p_interatomic_distance, p_lattice_constant); + } + + return PTM_NO_ERROR; +} + diff --git a/src/USER-PTM/initialize_data.cpp b/src/USER-PTM/initialize_data.cpp new file mode 100644 index 0000000000..6c177bfb70 --- /dev/null +++ b/src/USER-PTM/initialize_data.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include "initialize_data.h" + + +static void make_facets_clockwise(int num_facets, int8_t (*facets)[3], const double (*points)[3]) +{ + double plane_normal[3]; + double origin[3] = {0, 0, 0}; + + for (int i = 0;inum_graphs;i++) + { + int8_t code[2 * PTM_MAX_EDGES]; + int8_t degree[PTM_MAX_NBRS]; + int _max_degree = graph_degree(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree); + assert(_max_degree <= s->max_degree); + + make_facets_clockwise(s->num_facets, s->graphs[i].facets, &s->points[1]); + int ret = canonical_form_coloured(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree, colours, s->graphs[i].canonical_labelling, (int8_t*)&code[0], &s->graphs[i].hash); + if (ret != 0) + return ret; + } + + return PTM_NO_ERROR; +} + +bool ptm_initialized = false; +int ptm_initialize_global() +{ + if (ptm_initialized) + return PTM_NO_ERROR; + + int8_t colours[PTM_MAX_POINTS] = {0}; + int8_t dcolours[PTM_MAX_POINTS] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + int ret = initialize_graphs(&structure_sc, colours); + ret |= initialize_graphs(&structure_fcc, colours); + ret |= initialize_graphs(&structure_hcp, colours); + ret |= initialize_graphs(&structure_ico, colours); + ret |= initialize_graphs(&structure_bcc, colours); + ret |= initialize_graphs(&structure_dcub, dcolours); + ret |= initialize_graphs(&structure_dhex, dcolours); + + if (ret == PTM_NO_ERROR) + ptm_initialized = true; + + return ret; +} + +ptm_local_handle_t ptm_initialize_local() +{ + assert(ptm_initialized); + return (ptm_local_handle_t)voronoi_initialize_local(); +} + +void ptm_uninitialize_local(ptm_local_handle_t ptr) +{ + voronoi_uninitialize_local(ptr); +} + diff --git a/src/USER-PTM/initialize_data.h b/src/USER-PTM/initialize_data.h new file mode 100644 index 0000000000..644dfea8c4 --- /dev/null +++ b/src/USER-PTM/initialize_data.h @@ -0,0 +1,61 @@ +#ifndef INITIALIZE_DATA_H +#define INITIALIZE_DATA_H + + +#include "graph_data.h" +#include "graph_tools.h" +#include "deformation_gradient.h" +#include "fundamental_mappings.h" +#include "neighbour_ordering.h" +#include "canonical_coloured.h" +#include "convex_hull_incremental.h" + + +typedef struct +{ + int type; + int num_nbrs; + int num_facets; + int max_degree; + int num_graphs; + int num_mappings; + graph_t* graphs; + const double (*points)[3]; + const double (*penrose)[3]; + const int8_t (*mapping)[PTM_MAX_POINTS]; +} refdata_t; + + +//refdata_t structure_sc = { .type = PTM_MATCH_SC, .num_nbrs = 6, .num_facets = 8, .max_degree = 4, .num_graphs = NUM_SC_GRAPHS, .graphs = graphs_sc, .points = ptm_template_sc, .penrose = penrose_sc , .mapping = mapping_sc }; +const refdata_t structure_sc = { PTM_MATCH_SC, 6, 8, 4, NUM_SC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_sc, ptm_template_sc, penrose_sc, mapping_sc }; +const refdata_t structure_fcc = { PTM_MATCH_FCC, 12, 20, 6, NUM_FCC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_fcc, ptm_template_fcc, penrose_fcc, mapping_fcc }; +const refdata_t structure_hcp = { PTM_MATCH_HCP, 12, 20, 6, NUM_HCP_GRAPHS, NUM_HEX_MAPPINGS, graphs_hcp, ptm_template_hcp, penrose_hcp, mapping_hcp }; +const refdata_t structure_ico = { PTM_MATCH_ICO, 12, 20, 6, NUM_ICO_GRAPHS, NUM_ICO_MAPPINGS, graphs_ico, ptm_template_ico, penrose_ico, mapping_ico }; +const refdata_t structure_bcc = { PTM_MATCH_BCC, 14, 24, 8, NUM_BCC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_bcc, ptm_template_bcc, penrose_bcc, mapping_bcc }; +const refdata_t structure_dcub = { PTM_MATCH_DCUB, 16, 28, 8, NUM_DCUB_GRAPHS, NUM_DCUB_MAPPINGS, graphs_dcub, ptm_template_dcub, penrose_dcub, mapping_dcub }; +const refdata_t structure_dhex = { PTM_MATCH_DHEX, 16, 28, 8, NUM_DHEX_GRAPHS, NUM_DHEX_MAPPINGS, graphs_dhex, ptm_template_dhex, penrose_dhex, mapping_dhex }; + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ptm_local_handle* ptm_local_handle_t; +ptm_local_handle_t ptm_initialize_local(); +void ptm_uninitialize_local(ptm_local_handle_t ptr); + +int ptm_initialize_global(); + +//------------------------------------ +// global initialization switch +//------------------------------------ +extern bool ptm_initialized; + + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/src/USER-PTM/neighbour_ordering.cpp b/src/USER-PTM/neighbour_ordering.cpp new file mode 100644 index 0000000000..8e8b016cfc --- /dev/null +++ b/src/USER-PTM/neighbour_ordering.cpp @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#include +#include "ptm_constants.h" +#include "cell.h" +using namespace voro; + + + +typedef struct +{ + double area; + double dist; + int index; +} sorthelper_t; + +static bool sorthelper_compare(sorthelper_t const& a, sorthelper_t const& b) +{ + if (a.area > b.area) + return true; + + if (a.area < b.area) + return false; + + if (a.dist < b.dist) + return true; + + return false; +} + +//todo: change voronoi code to return errors rather than exiting +static int calculate_voronoi_face_areas(int num_points, const double (*_points)[3], double* normsq, double max_norm, voronoicell_neighbor* v, std::vector& nbr_indices, std::vector& face_areas) +{ + const double k = 1000 * max_norm; //todo: reduce this constant + v->init(-k,k,-k,k,-k,k); + + for (int i=1;inplane(x,y,z,normsq[i],i); + } + + v->neighbors(nbr_indices); + v->face_areas(face_areas); + return 0; +} + +int calculate_neighbour_ordering(void* _voronoi_handle, int num_points, const double (*_points)[3], int8_t* ordering) +{ + assert(num_points <= PTM_MAX_INPUT_POINTS); + + voronoicell_neighbor* voronoi_handle = (voronoicell_neighbor*)_voronoi_handle; + + double max_norm = 0; + double points[PTM_MAX_INPUT_POINTS][3]; + double normsq[PTM_MAX_INPUT_POINTS]; + for (int i = 0;i nbr_indices(num_points + 6); + std::vector face_areas(num_points + 6); + int ret = calculate_voronoi_face_areas(num_points, points, normsq, max_norm, voronoi_handle, nbr_indices, face_areas); + if (ret != 0) + return ret; + + double areas[PTM_MAX_INPUT_POINTS]; + memset(areas, 0, num_points * sizeof(double)); + areas[0] = INFINITY; + for (size_t i=0;i 0) + areas[index] = face_areas[i]; + } + + sorthelper_t data[PTM_MAX_INPUT_POINTS]; + for (int i=0;i= 3) + continue; + + ordering[1 + 4 + 3 * p + counts[p]] = q; + counts[p]++; + index++; + num_found++; + if (num_found >= 12) + break; + } + + if (num_found != 12) + return -1; + + for (int i=0;i + + +void subtract_barycentre(int num, double (*points)[3], double (*normalized)[3]) +{ + //calculate barycentre + double sum[3] = {0, 0, 0}; + for (int i=0;i nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Source: started anew. + * + * Change History: + * 2009/04/13 Started source + * 2010/03/28 Modified FastCalcRMSDAndRotation() to handle tiny qsqr + * If trying all rows of the adjoint still gives too small + * qsqr, then just return identity matrix. (DLT) + * 2010/06/30 Fixed prob in assigning A[9] = 0 in InnerProduct() + * invalid mem access + * 2011/02/21 Made CenterCoords use weights + * 2011/05/02 Finally changed CenterCoords declaration in qcprot.h + * Also changed some functions to static + * 2011/07/08 put in fabs() to fix taking sqrt of small neg numbers, fp error + * 2012/07/26 minor changes to comments and main.c, more info (v.1.4) + * + * 2016/05/29 QCP method adapted for polar decomposition of a 3x3 matrix, + * for use in Polyhedral Template Matching. + * + ******************************************************************************/ + +#include +#include +#include +#include "quat.h" + + +static void matmul_3x3(double* A, double* x, double* b) +{ + b[0] = A[0] * x[0] + A[1] * x[3] + A[2] * x[6]; + b[3] = A[3] * x[0] + A[4] * x[3] + A[5] * x[6]; + b[6] = A[6] * x[0] + A[7] * x[3] + A[8] * x[6]; + + b[1] = A[0] * x[1] + A[1] * x[4] + A[2] * x[7]; + b[4] = A[3] * x[1] + A[4] * x[4] + A[5] * x[7]; + b[7] = A[6] * x[1] + A[7] * x[4] + A[8] * x[7]; + + b[2] = A[0] * x[2] + A[1] * x[5] + A[2] * x[8]; + b[5] = A[3] * x[2] + A[4] * x[5] + A[5] * x[8]; + b[8] = A[6] * x[2] + A[7] * x[5] + A[8] * x[8]; +} + +static double matrix_determinant_3x3(double* A) +{ + return A[0] * (A[4]*A[8] - A[5]*A[7]) + - A[1] * (A[3]*A[8] - A[5]*A[6]) + + A[2] * (A[3]*A[7] - A[4]*A[6]); +} + +static void flip_matrix(double* A) +{ + for (int i=0;i<9;i++) + A[i] = -A[i]; +} + +static bool optimal_quaternion(double* A, bool polar, double E0, double* p_nrmsdsq, double* qopt) +{ + const double evecprec = 1e-6; + const double evalprec = 1e-11; + + double Sxx = A[0], Sxy = A[1], Sxz = A[2], + Syx = A[3], Syy = A[4], Syz = A[5], + Szx = A[6], Szy = A[7], Szz = A[8]; + + double Sxx2 = Sxx * Sxx, Syy2 = Syy * Syy, Szz2 = Szz * Szz, + Sxy2 = Sxy * Sxy, Syz2 = Syz * Syz, Sxz2 = Sxz * Sxz, + Syx2 = Syx * Syx, Szy2 = Szy * Szy, Szx2 = Szx * Szx; + + double fnorm_squared = Sxx2 + Syy2 + Szz2 + Sxy2 + Syz2 + Sxz2 + Syx2 + Szy2 + Szx2; + + double SyzSzymSyySzz2 = 2.0 * (Syz * Szy - Syy * Szz); + double Sxx2Syy2Szz2Syz2Szy2 = Syy2 + Szz2 - Sxx2 + Syz2 + Szy2; + double SxzpSzx = Sxz + Szx; + double SyzpSzy = Syz + Szy; + double SxypSyx = Sxy + Syx; + double SyzmSzy = Syz - Szy; + double SxzmSzx = Sxz - Szx; + double SxymSyx = Sxy - Syx; + double SxxpSyy = Sxx + Syy; + double SxxmSyy = Sxx - Syy; + double Sxy2Sxz2Syx2Szx2 = Sxy2 + Sxz2 - Syx2 - Szx2; + + double C[3]; + C[0] = Sxy2Sxz2Syx2Szx2 * Sxy2Sxz2Syx2Szx2 + + (Sxx2Syy2Szz2Syz2Szy2 + SyzSzymSyySzz2) * (Sxx2Syy2Szz2Syz2Szy2 - SyzSzymSyySzz2) + + (-(SxzpSzx)*(SyzmSzy)+(SxymSyx)*(SxxmSyy-Szz)) * (-(SxzmSzx)*(SyzpSzy)+(SxymSyx)*(SxxmSyy+Szz)) + + (-(SxzpSzx)*(SyzpSzy)-(SxypSyx)*(SxxpSyy-Szz)) * (-(SxzmSzx)*(SyzmSzy)-(SxypSyx)*(SxxpSyy+Szz)) + + (+(SxypSyx)*(SyzpSzy)+(SxzpSzx)*(SxxmSyy+Szz)) * (-(SxymSyx)*(SyzmSzy)+(SxzpSzx)*(SxxpSyy+Szz)) + + (+(SxypSyx)*(SyzmSzy)+(SxzmSzx)*(SxxmSyy-Szz)) * (-(SxymSyx)*(SyzpSzy)+(SxzmSzx)*(SxxpSyy-Szz)); + + C[1] = 8.0 * (Sxx*Syz*Szy + Syy*Szx*Sxz + Szz*Sxy*Syx - Sxx*Syy*Szz - Syz*Szx*Sxy - Szy*Syx*Sxz); + C[2] = -2.0 * fnorm_squared; + + //Newton-Raphson + double mxEigenV = polar ? sqrt(3 * fnorm_squared) : E0; + if (mxEigenV > evalprec) + { + for (int i=0;i<50;i++) + { + double oldg = mxEigenV; + double x2 = mxEigenV*mxEigenV; + double b = (x2 + C[2])*mxEigenV; + double a = b + C[1]; + double delta = ((a * mxEigenV + C[0]) / (2 * x2 * mxEigenV + b + a)); + mxEigenV -= delta; + if (fabs(mxEigenV - oldg) < fabs(evalprec * mxEigenV)) + break; + } + } + else + { + mxEigenV = 0.0; + } + + (*p_nrmsdsq) = std::max(0.0, 2.0 * (E0 - mxEigenV)); + + double a11 = SxxpSyy + Szz - mxEigenV; + double a12 = SyzmSzy; + double a13 = -SxzmSzx; + double a14 = SxymSyx; + + double a21 = SyzmSzy; + double a22 = SxxmSyy - Szz -mxEigenV; + double a23 = SxypSyx; + double a24 = SxzpSzx; + + double a31 = a13; + double a32 = a23; + double a33 = Syy - Sxx - Szz - mxEigenV; + double a34 = SyzpSzy; + + double a41 = a14; + double a42 = a24; + double a43 = a34; + double a44 = Szz - SxxpSyy - mxEigenV; + + double a3344_4334 = a33 * a44 - a43 * a34; + double a3244_4234 = a32 * a44 - a42 * a34; + double a3243_4233 = a32 * a43 - a42 * a33; + double a3143_4133 = a31 * a43 - a41 * a33; + double a3144_4134 = a31 * a44 - a41 * a34; + double a3142_4132 = a31 * a42 - a41 * a32; + double a1324_1423 = a13 * a24 - a14 * a23; + double a1224_1422 = a12 * a24 - a14 * a22; + double a1223_1322 = a12 * a23 - a13 * a22; + double a1124_1421 = a11 * a24 - a14 * a21; + double a1123_1321 = a11 * a23 - a13 * a21; + double a1122_1221 = a11 * a22 - a12 * a21; + + double q[4][4]; + q[0][0] = a12 * a3344_4334 - a13 * a3244_4234 + a14 * a3243_4233; + q[0][1] = -a11 * a3344_4334 + a13 * a3144_4134 - a14 * a3143_4133; + q[0][2] = a11 * a3244_4234 - a12 * a3144_4134 + a14 * a3142_4132; + q[0][3] = -a11 * a3243_4233 + a12 * a3143_4133 - a13 * a3142_4132; + + q[1][0] = a22 * a3344_4334 - a23 * a3244_4234 + a24 * a3243_4233; + q[1][1] = -a21 * a3344_4334 + a23 * a3144_4134 - a24 * a3143_4133; + q[1][2] = a21 * a3244_4234 - a22 * a3144_4134 + a24 * a3142_4132; + q[1][3] = -a21 * a3243_4233 + a22 * a3143_4133 - a23 * a3142_4132; + + q[2][0] = a32 * a1324_1423 - a33 * a1224_1422 + a34 * a1223_1322; + q[2][1] = -a31 * a1324_1423 + a33 * a1124_1421 - a34 * a1123_1321; + q[2][2] = a31 * a1224_1422 - a32 * a1124_1421 + a34 * a1122_1221; + q[2][3] = -a31 * a1223_1322 + a32 * a1123_1321 - a33 * a1122_1221; + + q[3][0] = a42 * a1324_1423 - a43 * a1224_1422 + a44 * a1223_1322; + q[3][1] = -a41 * a1324_1423 + a43 * a1124_1421 - a44 * a1123_1321; + q[3][2] = a41 * a1224_1422 - a42 * a1124_1421 + a44 * a1122_1221; + q[3][3] = -a41 * a1223_1322 + a42 * a1123_1321 - a43 * a1122_1221; + + double qsqr[4]; + for (int i=0;i<4;i++) + qsqr[i] = q[i][0]*q[i][0] + q[i][1]*q[i][1] + q[i][2]*q[i][2] + q[i][3]*q[i][3]; + + int bi = 0; + double max = 0; + for (int i=0;i<4;i++) + { + if (qsqr[i] > max) + { + bi = i; + max = qsqr[i]; + } + } + + bool too_small = false; + if (qsqr[bi] < evecprec) + { + //if qsqr is still too small, return the identity rotation. + q[bi][0] = 1; + q[bi][1] = 0; + q[bi][2] = 0; + q[bi][3] = 0; + too_small = true; + } + else + { + double normq = sqrt(qsqr[bi]); + q[bi][0] /= normq; + q[bi][1] /= normq; + q[bi][2] /= normq; + q[bi][3] /= normq; + } + + memcpy(qopt, q[bi], 4 * sizeof(double)); + return !too_small; +} + +int polar_decomposition_3x3(double* _A, bool right_sided, double* U, double* P) +{ + double A[9]; + memcpy(A, _A, 9 * sizeof(double)); + + double det = matrix_determinant_3x3(A); + if (det < 0) + flip_matrix(A); + + double q[4]; + double nrmsdsq = 0; + optimal_quaternion(A, true, -1, &nrmsdsq, q); + q[0] = -q[0]; + quaternion_to_rotation_matrix(q, U); + + if (det < 0) + flip_matrix(U); + + double UT[9] = {U[0], U[3], U[6], U[1], U[4], U[7], U[2], U[5], U[8]}; + + if (right_sided) + matmul_3x3(UT, _A, P); + else + matmul_3x3(_A, UT, P); + + return 0; +} + +void InnerProduct(double *A, int num, const double (*coords1)[3], double (*coords2)[3], int8_t* permutation) +{ + A[0] = A[1] = A[2] = A[3] = A[4] = A[5] = A[6] = A[7] = A[8] = 0.0; + + for (int i = 0; i < num; ++i) + { + double x1 = coords1[i][0]; + double y1 = coords1[i][1]; + double z1 = coords1[i][2]; + + double x2 = coords2[permutation[i]][0]; + double y2 = coords2[permutation[i]][1]; + double z2 = coords2[permutation[i]][2]; + + A[0] += x1 * x2; + A[1] += x1 * y2; + A[2] += x1 * z2; + + A[3] += y1 * x2; + A[4] += y1 * y2; + A[5] += y1 * z2; + + A[6] += z1 * x2; + A[7] += z1 * y2; + A[8] += z1 * z2; + } +} + +int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, double* U) +{ + optimal_quaternion(A, false, E0, p_nrmsdsq, q); + quaternion_to_rotation_matrix(q, U); + return 0; +} + diff --git a/src/USER-PTM/polar.h b/src/USER-PTM/polar.h new file mode 100644 index 0000000000..3ec025b806 --- /dev/null +++ b/src/USER-PTM/polar.h @@ -0,0 +1,12 @@ +#ifndef POLAR_H +#define POLAR_H + +#include +#include + +int polar_decomposition_3x3(double* _A, bool right_sided, double* U, double* P); +void InnerProduct(double *A, int num, const double (*coords1)[3], double (*coords2)[3], int8_t* permutation); +int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, double* U); + +#endif + diff --git a/src/USER-PTM/ptm_constants.h b/src/USER-PTM/ptm_constants.h new file mode 100644 index 0000000000..f868f51e84 --- /dev/null +++ b/src/USER-PTM/ptm_constants.h @@ -0,0 +1,174 @@ +#ifndef PTM_CONSTANTS_H +#define PTM_CONSTANTS_H + +//------------------------------------ +// definitions +//------------------------------------ +#define PTM_NO_ERROR 0 + + +#define PTM_CHECK_FCC (1 << 0) +#define PTM_CHECK_HCP (1 << 1) +#define PTM_CHECK_BCC (1 << 2) +#define PTM_CHECK_ICO (1 << 3) +#define PTM_CHECK_SC (1 << 4) +#define PTM_CHECK_DCUB (1 << 5) +#define PTM_CHECK_DHEX (1 << 6) +#define PTM_CHECK_NONDIAMOND (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC) +#define PTM_CHECK_ALL (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC | PTM_CHECK_DCUB | PTM_CHECK_DHEX) + +#define PTM_MATCH_NONE 0 +#define PTM_MATCH_FCC 1 +#define PTM_MATCH_HCP 2 +#define PTM_MATCH_BCC 3 +#define PTM_MATCH_ICO 4 +#define PTM_MATCH_SC 5 +#define PTM_MATCH_DCUB 6 +#define PTM_MATCH_DHEX 7 + +#define PTM_ALLOY_NONE 0 +#define PTM_ALLOY_PURE 1 +#define PTM_ALLOY_L10 2 +#define PTM_ALLOY_L12_CU 3 +#define PTM_ALLOY_L12_AU 4 +#define PTM_ALLOY_B2 5 +#define PTM_ALLOY_SIC 6 + + +#define PTM_MAX_INPUT_POINTS 35 +#define PTM_MAX_NBRS 16 +#define PTM_MAX_POINTS (PTM_MAX_NBRS + 1) +#define PTM_MAX_FACETS 28 //2 * PTM_MAX_NBRS - 4 +#define PTM_MAX_EDGES 42 //3 * PTM_MAX_NBRS - 6 + + +//------------------------------------ +// number of neighbours +//------------------------------------ +#define PTM_NUM_NBRS_FCC 12 +#define PTM_NUM_NBRS_HCP 12 +#define PTM_NUM_NBRS_BCC 14 +#define PTM_NUM_NBRS_ICO 12 +#define PTM_NUM_NBRS_SC 6 +#define PTM_NUM_NBRS_DCUB 16 +#define PTM_NUM_NBRS_DHEX 16 + +#define PTM_NUM_POINTS_FCC (PTM_NUM_NBRS_FCC + 1) +#define PTM_NUM_POINTS_HCP (PTM_NUM_NBRS_HCP + 1) +#define PTM_NUM_POINTS_BCC (PTM_NUM_NBRS_BCC + 1) +#define PTM_NUM_POINTS_ICO (PTM_NUM_NBRS_ICO + 1) +#define PTM_NUM_POINTS_SC (PTM_NUM_NBRS_SC + 1) +#define PTM_NUM_POINTS_DCUB (PTM_NUM_NBRS_DCUB + 1) +#define PTM_NUM_POINTS_DHEX (PTM_NUM_NBRS_DHEX + 1) + +const int ptm_num_nbrs[8] = {0, PTM_NUM_NBRS_FCC, PTM_NUM_NBRS_HCP, PTM_NUM_NBRS_BCC, PTM_NUM_NBRS_ICO, PTM_NUM_NBRS_SC, PTM_NUM_NBRS_DCUB, PTM_NUM_NBRS_DHEX}; + +//------------------------------------ +// template structures +//------------------------------------ + +//these point sets have barycentre {0, 0, 0} and are scaled such that the mean neighbour distance is 1 + +const double ptm_template_fcc[PTM_NUM_POINTS_FCC][3] = { { 0. , 0. , 0. }, + { 0. , 0.707106781187, 0.707106781187 }, + { 0. , -0.707106781187, -0.707106781187 }, + { 0. , 0.707106781187, -0.707106781187 }, + { 0. , -0.707106781187, 0.707106781187 }, + { 0.707106781187, 0. , 0.707106781187 }, + { -0.707106781187, 0. , -0.707106781187 }, + { 0.707106781187, 0. , -0.707106781187 }, + { -0.707106781187, 0. , 0.707106781187 }, + { 0.707106781187, 0.707106781187, 0. }, + { -0.707106781187, -0.707106781187, 0. }, + { 0.707106781187, -0.707106781187, 0. }, + { -0.707106781187, 0.707106781187, 0. } }; + +const double ptm_template_hcp[PTM_NUM_POINTS_HCP][3] = { { 0. , 0. , 0. }, + { 0.707106781186, 0. , 0.707106781186 }, + { -0.235702260395, -0.942809041583, -0.235702260395 }, + { 0.707106781186, 0.707106781186, 0. }, + { -0.235702260395, -0.235702260395, -0.942809041583 }, + { 0. , 0.707106781186, 0.707106781186 }, + { -0.942809041583, -0.235702260395, -0.235702260395 }, + { -0.707106781186, 0.707106781186, 0. }, + { 0. , 0.707106781186, -0.707106781186 }, + { 0.707106781186, 0. , -0.707106781186 }, + { 0.707106781186, -0.707106781186, 0. }, + { -0.707106781186, 0. , 0.707106781186 }, + { 0. , -0.707106781186, 0.707106781186 } }; + +const double ptm_template_bcc[PTM_NUM_POINTS_BCC][3] = { { 0. , 0. , 0. }, + { -0.541451884327, -0.541451884327, -0.541451884327 }, + { 0.541451884327, 0.541451884327, 0.541451884327 }, + { 0.541451884327, -0.541451884327, -0.541451884327 }, + { -0.541451884327, 0.541451884327, 0.541451884327 }, + { -0.541451884327, 0.541451884327, -0.541451884327 }, + { 0.541451884327, -0.541451884327, 0.541451884327 }, + { -0.541451884327, -0.541451884327, 0.541451884327 }, + { 0.541451884327, 0.541451884327, -0.541451884327 }, + { 0. , 0. , -1.082903768655 }, + { 0. , 0. , 1.082903768655 }, + { 0. , -1.082903768655, 0. }, + { 0. , 1.082903768655, 0. }, + { -1.082903768655, 0. , 0. }, + { 1.082903768655, 0. , 0. } }; + +const double ptm_template_ico[PTM_NUM_POINTS_ICO][3] = { { 0. , 0. , 0. }, + { 0. , 0.525731112119, 0.850650808352 }, + { 0. , -0.525731112119, -0.850650808352 }, + { 0. , 0.525731112119, -0.850650808352 }, + { 0. , -0.525731112119, 0.850650808352 }, + { -0.525731112119, -0.850650808352, 0. }, + { 0.525731112119, 0.850650808352, 0. }, + { 0.525731112119, -0.850650808352, 0. }, + { -0.525731112119, 0.850650808352, 0. }, + { -0.850650808352, 0. , -0.525731112119 }, + { 0.850650808352, 0. , 0.525731112119 }, + { 0.850650808352, 0. , -0.525731112119 }, + { -0.850650808352, 0. , 0.525731112119 } }; + +const double ptm_template_sc[PTM_NUM_POINTS_SC][3] = { { 0. , 0. , 0. }, + { 0. , 0. , -1. }, + { 0. , 0. , 1. }, + { 0. , -1. , 0. }, + { 0. , 1. , 0. }, + { -1. , 0. , 0. }, + { 1. , 0. , 0. } }; + +const double ptm_template_dcub[PTM_NUM_POINTS_DCUB][3] = { { 0. , 0. , 0. }, + { -0.391491627053, 0.391491627053, 0.391491627053 }, + { -0.391491627053, -0.391491627053, -0.391491627053 }, + { 0.391491627053, -0.391491627053, 0.391491627053 }, + { 0.391491627053, 0.391491627053, -0.391491627053 }, + { -0.782983254107, 0. , 0.782983254107 }, + { -0.782983254107, 0.782983254107, 0. }, + { 0. , 0.782983254107, 0.782983254107 }, + { -0.782983254107, -0.782983254107, 0. }, + { -0.782983254107, 0. , -0.782983254107 }, + { 0. , -0.782983254107, -0.782983254107 }, + { 0. , -0.782983254107, 0.782983254107 }, + { 0.782983254107, -0.782983254107, 0. }, + { 0.782983254107, 0. , 0.782983254107 }, + { 0. , 0.782983254107, -0.782983254107 }, + { 0.782983254107, 0. , -0.782983254107 }, + { 0.782983254107, 0.782983254107, 0. } }; + +const double ptm_template_dhex[PTM_NUM_POINTS_DHEX][3] = { { 0. , 0. , 0. }, + { -0.391491627053, -0.391491627053, -0.391491627053 }, + { 0.391491627053, -0.391491627053, 0.391491627053 }, + { -0.391491627053, 0.391491627053, 0.391491627053 }, + { 0.391491627053, 0.391491627053, -0.391491627053 }, + { -0.260994418036, -1.043977672142, -0.260994418036 }, + { -1.043977672142, -0.260994418036, -0.260994418036 }, + { -0.260994418036, -0.260994418036, -1.043977672142 }, + { 0.782983254107, 0. , 0.782983254107 }, + { 0.782983254107, -0.782983254107, 0. }, + { 0. , -0.782983254107, 0.782983254107 }, + { 0. , 0.782983254107, 0.782983254107 }, + { -0.782983254107, 0.782983254107, 0. }, + { -0.782983254107, 0. , 0.782983254107 }, + { 0.782983254107, 0.782983254107, 0. }, + { 0. , 0.782983254107, -0.782983254107 }, + { 0.782983254107, 0. , -0.782983254107 } }; +#endif + diff --git a/src/USER-PTM/ptm_functions.h b/src/USER-PTM/ptm_functions.h new file mode 100644 index 0000000000..69141a37c4 --- /dev/null +++ b/src/USER-PTM/ptm_functions.h @@ -0,0 +1,27 @@ +#ifndef PTM_FUNCTIONS_H +#define PTM_FUNCTIONS_H + +#include +#include +#include "initialize_data.h" +#include "ptm_constants.h" + + +//------------------------------------ +// function declarations +//------------------------------------ +#ifdef __cplusplus +extern "C" { +#endif + + +int ptm_index( ptm_local_handle_t local_handle, int32_t flags, int num_points, double (*atomic_positions)[3], int32_t* atomic_numbers, bool topological_ordering, //inputs + int32_t* p_type, int32_t* p_alloy_type, double* p_scale, double* p_rmsd, double* q, double* F, double* F_res, double* U, double* P, int8_t* mapping, double* p_interatomic_distance, double* p_lattice_constant); //outputs + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/USER-PTM/quat.cpp b/src/USER-PTM/quat.cpp new file mode 100644 index 0000000000..f55aff3d2b --- /dev/null +++ b/src/USER-PTM/quat.cpp @@ -0,0 +1,396 @@ +#include +#include +#include + + +#define SIGN(x) (x >= 0 ? 1 : -1) +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) +#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) + + +#define SQRT_2 1.4142135623730951454746218587388284504414 +#define HALF_SQRT_2 0.7071067811865474617150084668537601828575 + +#define PHI 1.6180339887498949025257388711906969547272 +#define HALF_PHI 0.8090169943749474512628694355953484773636 + +#define INV_PHI 0.6180339887498947915034364086750429123640 +#define HALF_INV_PHI 0.3090169943749473957517182043375214561820 + +#define SQRT_5_ 2.23606797749978969640917366873127623544061835961152572427089 +#define SQRT_2_3 0.8164965809277260344600790631375275552273 +#define SQRT_1_6 0.4082482904638630172300395315687637776136 + + +double generator_cubic[24][4] = { {1, 0, 0, 0 }, + {0, 1, 0, 0 }, + {0, 0, 1, 0 }, + {0, 0, 0, 1 }, + {0.5, 0.5, 0.5, 0.5 }, + {0.5, 0.5, -0.5, 0.5 }, + {0.5, -0.5, 0.5, 0.5 }, + {0.5, -0.5, -0.5, 0.5 }, + {-0.5, 0.5, 0.5, 0.5 }, + {-0.5, 0.5, -0.5, 0.5 }, + {-0.5, -0.5, 0.5, 0.5 }, + {-0.5, -0.5, -0.5, 0.5 }, + {HALF_SQRT_2, HALF_SQRT_2, 0, 0 }, + {HALF_SQRT_2, 0, HALF_SQRT_2, 0 }, + {HALF_SQRT_2, 0, 0, HALF_SQRT_2 }, + {-HALF_SQRT_2, HALF_SQRT_2, 0, 0 }, + {-HALF_SQRT_2, 0, HALF_SQRT_2, 0 }, + {-HALF_SQRT_2, 0, 0, HALF_SQRT_2 }, + {0, HALF_SQRT_2, HALF_SQRT_2, 0 }, + {0, HALF_SQRT_2, 0, HALF_SQRT_2 }, + {0, 0, HALF_SQRT_2, HALF_SQRT_2 }, + {0, -HALF_SQRT_2, HALF_SQRT_2, 0 }, + {0, -HALF_SQRT_2, 0, HALF_SQRT_2 }, + {0, 0, -HALF_SQRT_2, HALF_SQRT_2 } }; + +double generator_diamond_cubic[12][4] = { {1, 0, 0, 0 }, + {0, 1, 0, 0 }, + {0, 0, 1, 0 }, + {0, 0, 0, 1 }, + {0.5, 0.5, 0.5, 0.5 }, + {0.5, 0.5, -0.5, 0.5 }, + {0.5, -0.5, 0.5, 0.5 }, + {0.5, -0.5, -0.5, 0.5 }, + {-0.5, 0.5, 0.5, 0.5 }, + {-0.5, 0.5, -0.5, 0.5 }, + {-0.5, -0.5, 0.5, 0.5 }, + {-0.5, -0.5, -0.5, 0.5 } }; + +double generator_hcp[6][4] = { {1, 0, 0, 0}, + {0.5, 0.5, 0.5, 0.5}, + {0.5, -0.5, -0.5, -0.5}, + {0, SQRT_2_3, -SQRT_1_6, -SQRT_1_6}, + {0, SQRT_1_6, -SQRT_2_3, SQRT_1_6}, + {0, SQRT_1_6, SQRT_1_6, -SQRT_2_3} }; + +double generator_diamond_hexagonal[3][4] = { {1, 0, 0, 0}, + {0.5, 0.5, 0.5, 0.5}, + {0.5, -0.5, -0.5, -0.5} }; + +double generator_icosahedral[60][4] = { {1, 0, 0, 0}, + {HALF_PHI, -HALF_INV_PHI, -0.5, 0}, + {HALF_PHI, 0, -HALF_INV_PHI, -0.5}, + {HALF_PHI, -0.5, 0, -HALF_INV_PHI}, + {HALF_PHI, HALF_INV_PHI, -0.5, 0}, + {HALF_PHI, 0, HALF_INV_PHI, -0.5}, + {HALF_PHI, -0.5, 0, HALF_INV_PHI}, + {HALF_PHI, 0.5, 0, -HALF_INV_PHI}, + {HALF_PHI, 0, -HALF_INV_PHI, 0.5}, + {HALF_PHI, -HALF_INV_PHI, 0.5, 0}, + {HALF_PHI, 0, HALF_INV_PHI, 0.5}, + {HALF_PHI, HALF_INV_PHI, 0.5, 0}, + {HALF_PHI, 0.5, 0, HALF_INV_PHI}, + {0.5, HALF_PHI, -HALF_INV_PHI, 0}, + {0.5, HALF_PHI, HALF_INV_PHI, 0}, + {0.5, 0.5, 0.5, 0.5}, + {0.5, 0.5, 0.5, -0.5}, + {0.5, 0.5, -0.5, 0.5}, + {0.5, 0.5, -0.5, -0.5}, + {0.5, HALF_INV_PHI, 0, HALF_PHI}, + {0.5, HALF_INV_PHI, 0, -HALF_PHI}, + {0.5, 0, HALF_PHI, -HALF_INV_PHI}, + {0.5, 0, HALF_PHI, HALF_INV_PHI}, + {0.5, 0, -HALF_PHI, -HALF_INV_PHI}, + {0.5, 0, -HALF_PHI, HALF_INV_PHI}, + {0.5, -HALF_INV_PHI, 0, HALF_PHI}, + {0.5, -HALF_INV_PHI, 0, -HALF_PHI}, + {0.5, -0.5, 0.5, 0.5}, + {0.5, -0.5, 0.5, -0.5}, + {0.5, -0.5, -0.5, 0.5}, + {0.5, -0.5, -0.5, -0.5}, + {0.5, -HALF_PHI, -HALF_INV_PHI, 0}, + {0.5, -HALF_PHI, HALF_INV_PHI, 0}, + {HALF_INV_PHI, -HALF_PHI, 0, -0.5}, + {HALF_INV_PHI, 0, -0.5, -HALF_PHI}, + {HALF_INV_PHI, -0.5, -HALF_PHI, 0}, + {HALF_INV_PHI, 0, 0.5, -HALF_PHI}, + {HALF_INV_PHI, -HALF_PHI, 0, 0.5}, + {HALF_INV_PHI, 0.5, -HALF_PHI, 0}, + {HALF_INV_PHI, HALF_PHI, 0, -0.5}, + {HALF_INV_PHI, -0.5, HALF_PHI, 0}, + {HALF_INV_PHI, 0, -0.5, HALF_PHI}, + {HALF_INV_PHI, HALF_PHI, 0, 0.5}, + {HALF_INV_PHI, 0, 0.5, HALF_PHI}, + {HALF_INV_PHI, 0.5, HALF_PHI, 0}, + {0, 1, 0, 0}, + {0, HALF_PHI, -0.5, HALF_INV_PHI}, + {0, HALF_PHI, -0.5, -HALF_INV_PHI}, + {0, HALF_PHI, 0.5, HALF_INV_PHI}, + {0, HALF_PHI, 0.5, -HALF_INV_PHI}, + {0, 0.5, HALF_INV_PHI, -HALF_PHI}, + {0, 0.5, HALF_INV_PHI, HALF_PHI}, + {0, 0.5, -HALF_INV_PHI, -HALF_PHI}, + {0, 0.5, -HALF_INV_PHI, HALF_PHI}, + {0, HALF_INV_PHI, -HALF_PHI, 0.5}, + {0, HALF_INV_PHI, -HALF_PHI, -0.5}, + {0, HALF_INV_PHI, HALF_PHI, 0.5}, + {0, HALF_INV_PHI, HALF_PHI, -0.5}, + {0, 0, 1, 0}, + {0, 0, 0, 1} }; + +static void quat_rot(double* r, double* a, double* b) +{ + b[0] = (r[0] * a[0] - r[1] * a[1] - r[2] * a[2] - r[3] * a[3]); + b[1] = (r[0] * a[1] + r[1] * a[0] + r[2] * a[3] - r[3] * a[2]); + b[2] = (r[0] * a[2] - r[1] * a[3] + r[2] * a[0] + r[3] * a[1]); + b[3] = (r[0] * a[3] + r[1] * a[2] - r[2] * a[1] + r[3] * a[0]); +} + +static int rotate_quaternion_into_fundamental_zone(int num_generators, double (*generator)[4], double* q) +{ + double max = 0.0; + int i = 0, bi = -1; + for (i=0;i max) + { + max = t; + bi = i; + } + } + + double f[4]; + quat_rot(q, generator[bi], f); + memcpy(q, &f, 4 * sizeof(double)); + if (q[0] < 0) + { + q[0] = -q[0]; + q[1] = -q[1]; + q[2] = -q[2]; + q[3] = -q[3]; + } + + return bi; +} + +int rotate_quaternion_into_cubic_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(24, generator_cubic, q); +} + +int rotate_quaternion_into_diamond_cubic_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(12, generator_diamond_cubic, q); +} + +int rotate_quaternion_into_icosahedral_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(60, generator_icosahedral, q); +} + +int rotate_quaternion_into_hcp_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(6, generator_hcp, q); +} + +int rotate_quaternion_into_diamond_hexagonal_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(3, generator_diamond_hexagonal, q); +} + +double quat_dot(double* a, double* b) +{ + return a[0] * b[0] + + a[1] * b[1] + + a[2] * b[2] + + a[3] * b[3]; +} + +double quat_size(double* q) +{ + return sqrt(quat_dot(q, q)); +} + +void normalize_quaternion(double* q) +{ + double size = quat_size(q); + + q[0] /= size; + q[1] /= size; + q[2] /= size; + q[3] /= size; +} + +void rotation_matrix_to_quaternion(double* u, double* q) +{ + double r11 = u[0]; + double r12 = u[1]; + double r13 = u[2]; + double r21 = u[3]; + double r22 = u[4]; + double r23 = u[5]; + double r31 = u[6]; + double r32 = u[7]; + double r33 = u[8]; + + q[0] = (1.0 + r11 + r22 + r33) / 4.0; + q[1] = (1.0 + r11 - r22 - r33) / 4.0; + q[2] = (1.0 - r11 + r22 - r33) / 4.0; + q[3] = (1.0 - r11 - r22 + r33) / 4.0; + + q[0] = sqrt(MAX(0, q[0])); + q[1] = sqrt(MAX(0, q[1])); + q[2] = sqrt(MAX(0, q[2])); + q[3] = sqrt(MAX(0, q[3])); + + double m0 = MAX(q[0], q[1]); + double m1 = MAX(q[2], q[3]); + double max = MAX(m0, m1); + + int i = 0; + for (i=0;i<4;i++) + if (q[i] == max) + break; + + if (i == 0) + { + q[1] *= SIGN(r32 - r23); + q[2] *= SIGN(r13 - r31); + q[3] *= SIGN(r21 - r12); + } + else if (i == 1) + { + q[0] *= SIGN(r32 - r23); + q[2] *= SIGN(r21 + r12); + q[3] *= SIGN(r13 + r31); + } + else if (i == 2) + { + q[0] *= SIGN(r13 - r31); + q[1] *= SIGN(r21 + r12); + q[3] *= SIGN(r32 + r23); + } + else if (i == 3) + { + q[0] *= SIGN(r21 - r12); + q[1] *= SIGN(r31 + r13); + q[2] *= SIGN(r32 + r23); + } + + normalize_quaternion(q); +} + +void quaternion_to_rotation_matrix(double* q, double* u) +{ + double a = q[0]; + double b = q[1]; + double c = q[2]; + double d = q[3]; + + u[0] = a*a + b*b - c*c - d*d; + u[1] = 2*b*c - 2*a*d; + u[2] = 2*b*d + 2*a*c; + + u[3] = 2*b*c + 2*a*d; + u[4] = a*a - b*b + c*c - d*d; + u[5] = 2*c*d - 2*a*b; + + u[6] = 2*b*d - 2*a*c; + u[7] = 2*c*d + 2*a*b; + u[8] = a*a - b*b - c*c + d*d; +} + +double quat_quick_misorientation(double* q1, double* q2) +{ + double t = quat_dot(q1, q2); + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_misorientation(double* q1, double* q2) +{ + return acos(quat_quick_misorientation(q1, q2)); +} + + +double quat_quick_disorientation_cubic(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_cubic_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_cubic(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_cubic(q0, q1)); +} + +double quat_quick_disorientation_diamond_cubic(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_diamond_cubic_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_diamond_cubic(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_diamond_cubic(q0, q1)); +} + +double quat_quick_disorientation_hcp(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_hcp_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_hcp(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_hcp(q0, q1)); +} + +double quat_quick_disorientation_diamond_hexagonal(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_diamond_hexagonal_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_diamond_hexagonal(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_diamond_hexagonal(q0, q1)); +} + +double quat_quick_disorientation_icosahedral(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_icosahedral_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_icosahedral(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_icosahedral(q0, q1)); +} + diff --git a/src/USER-PTM/quat.h b/src/USER-PTM/quat.h new file mode 100644 index 0000000000..725086322c --- /dev/null +++ b/src/USER-PTM/quat.h @@ -0,0 +1,32 @@ +#ifndef QUAT_H +#define QUAT_H + +int rotate_quaternion_into_cubic_fundamental_zone(double* q); +int rotate_quaternion_into_diamond_cubic_fundamental_zone(double* q); +int rotate_quaternion_into_icosahedral_fundamental_zone(double* q); +int rotate_quaternion_into_hcp_fundamental_zone(double* q); +int rotate_quaternion_into_diamond_hexagonal_fundamental_zone(double* q); + +void normalize_quaternion(double* q); +void quaternion_to_rotation_matrix(double* q, double* U); +void rotation_matrix_to_quaternion(double* u, double* q); +double quat_dot(double* a, double* b); +double quat_quick_misorientation(double* q1, double* q2); +double quat_misorientation(double* q1, double* q2); + +double quat_quick_disorientation_cubic(double* q0, double* q1); +double quat_disorientation_cubic(double* q0, double* q1); +double quat_quick_disorientation_diamond_cubic(double* q0, double* q1); +double quat_disorientation_diamond_cubic(double* q0, double* q1); +double quat_quick_disorientation_hcp(double* q0, double* q1); +double quat_disorientation_hcp(double* q0, double* q1); +double quat_quick_disorientation_diamond_hexagonal(double* q0, double* q1); +double quat_disorientation_diamond_hexagonal(double* q0, double* q1); +double quat_quick_disorientation_icosahedral(double* q0, double* q1); +double quat_disorientation_icosahedral(double* q0, double* q1); + +#endif + + + + diff --git a/src/USER-PTM/structure_matcher.cpp b/src/USER-PTM/structure_matcher.cpp new file mode 100644 index 0000000000..dad8e3599a --- /dev/null +++ b/src/USER-PTM/structure_matcher.cpp @@ -0,0 +1,294 @@ +#include +#include +#include +#include +#include +#include +#include +#include "convex_hull_incremental.h" +#include "canonical_coloured.h" +#include "graph_data.h" +#include "graph_tools.h" +#include "normalize_vertices.h" +#include "polar.h" +#include "structure_matcher.h" +#include "ptm_constants.h" + + +static double calc_rmsd(int num_points, const double (*ideal_points)[3], double (*normalized)[3], int8_t* mapping, + double G1, double G2, double E0, double* q, double* p_scale) +{ + double A0[9]; + InnerProduct(A0, num_points, ideal_points, normalized, mapping); + + double nrmsdsq, rot[9]; + FastCalcRMSDAndRotation(A0, E0, &nrmsdsq, q, rot); + + double k0 = 0; + for (int i=0;inum_nbrs + 1; + const double (*ideal_points)[3] = s->points; + int8_t inverse_labelling[PTM_MAX_POINTS]; + int8_t mapping[PTM_MAX_POINTS]; + + for (int i=0; inum_graphs;i++) + { + if (hash != s->graphs[i].hash) + continue; + + graph_t* gref = &s->graphs[i]; + for (int j = 0;jnum_automorphisms;j++) + { + for (int k=0;kautomorphism_index + j][k]] = inverse_labelling[ gref->canonical_labelling[k] ]; + + double q[4], scale = 0; + double rmsd = calc_rmsd(num_points, ideal_points, normalized, mapping, G1, G2, E0, q, &scale); + if (rmsd < res->rmsd) + { + res->rmsd = rmsd; + res->scale = scale; + res->ref_struct = s; + memcpy(res->q, q, 4 * sizeof(double)); + memcpy(res->mapping, mapping, sizeof(int8_t) * num_points); + } + } + } +} + +int match_general(const refdata_t* s, double (*ch_points)[3], double (*points)[3], convexhull_t* ch, result_t* res) +{ + int8_t degree[PTM_MAX_NBRS]; + int8_t facets[PTM_MAX_FACETS][3]; + + int ret = get_convex_hull(s->num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); + ch->ok = ret >= 0; + if (ret != 0) + return PTM_NO_ERROR; + + if (ch->num_facets != s->num_facets) + return PTM_NO_ERROR; //incorrect number of facets in convex hull + + int max_degree = graph_degree(s->num_facets, facets, s->num_nbrs, degree); + if (max_degree > s->max_degree) + return PTM_NO_ERROR; + + if (s->type == PTM_MATCH_SC) + for (int i = 0;inum_nbrs;i++) + if (degree[i] != 4) + return PTM_NO_ERROR; + + double normalized[PTM_MAX_POINTS][3]; + subtract_barycentre(s->num_nbrs + 1, points, normalized); + + int8_t code[2 * PTM_MAX_EDGES]; + int8_t colours[PTM_MAX_POINTS] = {0}; + int8_t canonical_labelling[PTM_MAX_POINTS]; + uint64_t hash = 0; + ret = canonical_form_coloured(s->num_facets, facets, s->num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); + if (ret != PTM_NO_ERROR) + return ret; + + check_graphs(s, hash, canonical_labelling, normalized, res); + return PTM_NO_ERROR; +} + +int match_fcc_hcp_ico(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res) +{ + int num_nbrs = structure_fcc.num_nbrs; + int num_facets = structure_fcc.num_facets; + int max_degree = structure_fcc.max_degree; + + int8_t degree[PTM_MAX_NBRS]; + int8_t facets[PTM_MAX_FACETS][3]; + + int ret = get_convex_hull(num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); + ch->ok = ret >= 0; + if (ret != 0) + return PTM_NO_ERROR; + + if (ch->num_facets != num_facets) + return PTM_NO_ERROR; //incorrect number of facets in convex hull + + int _max_degree = graph_degree(num_facets, facets, num_nbrs, degree); + if (_max_degree > max_degree) + return PTM_NO_ERROR; + + double normalized[PTM_MAX_POINTS][3]; + subtract_barycentre(num_nbrs + 1, points, normalized); + + int8_t code[2 * PTM_MAX_EDGES]; + int8_t colours[PTM_MAX_POINTS] = {0}; + int8_t canonical_labelling[PTM_MAX_POINTS]; + uint64_t hash = 0; + ret = canonical_form_coloured(num_facets, facets, num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); + if (ret != PTM_NO_ERROR) + return ret; + + if (flags & PTM_CHECK_FCC) check_graphs(&structure_fcc, hash, canonical_labelling, normalized, res); + if (flags & PTM_CHECK_HCP) check_graphs(&structure_hcp, hash, canonical_labelling, normalized, res); + if (flags & PTM_CHECK_ICO) check_graphs(&structure_ico, hash, canonical_labelling, normalized, res); + return PTM_NO_ERROR; +} + +int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res) +{ + int num_nbrs = structure_dcub.num_nbrs; + int num_facets = structure_fcc.num_facets; + int max_degree = structure_dcub.max_degree; + + + int8_t facets[PTM_MAX_FACETS][3]; + int ret = get_convex_hull(num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); + ch->ok = ret >= 0; + if (ret != 0) + return PTM_NO_ERROR; + + //check for facets with multiple inner atoms + bool inverted[4] = {false, false, false, false}; + for (int i=0;inum_facets;i++) + { + int n = 0; + for (int j=0;j<3;j++) + { + if (facets[i][j] <= 3) + { + inverted[facets[i][j]] = true; + n++; + } + } + if (n > 1) + return PTM_NO_ERROR; + } + + int num_inverted = 0; + for (int i=0;i<4;i++) + num_inverted += inverted[i] ? 1 : 0; + + if (ch->num_facets != num_facets + 2 * num_inverted) + return PTM_NO_ERROR; //incorrect number of facets in convex hull + + int8_t degree[PTM_MAX_NBRS]; + int _max_degree = graph_degree(num_facets, facets, num_nbrs, degree); + if (_max_degree > max_degree) + return PTM_NO_ERROR; + + int num_found = 0; + int8_t toadd[4][3]; + for (int i=0;inum_facets;i++) + { + int a = facets[i][0]; + int b = facets[i][1]; + int c = facets[i][2]; + if (a <= 3 || b <= 3 || c <= 3) + continue; + + int i0 = (a - 4) / 3; + int i1 = (b - 4) / 3; + int i2 = (c - 4) / 3; + + if (i0 == i1 && i0 == i2) + { + if (num_found + num_inverted >= 4) + return PTM_NO_ERROR; + + toadd[num_found][0] = a; + toadd[num_found][1] = b; + toadd[num_found][2] = c; + num_found++; + + memcpy(&facets[i], &facets[ch->num_facets - 1], 3 * sizeof(int8_t)); + ch->num_facets--; + i--; + } + } + + if (num_found + num_inverted != 4) + return PTM_NO_ERROR; + + for (int i=0;inum_facets][0] = i0; + facets[ch->num_facets][1] = b; + facets[ch->num_facets][2] = c; + ch->num_facets++; + + facets[ch->num_facets][0] = a; + facets[ch->num_facets][1] = i0; + facets[ch->num_facets][2] = c; + ch->num_facets++; + + facets[ch->num_facets][0] = a; + facets[ch->num_facets][1] = b; + facets[ch->num_facets][2] = i0; + ch->num_facets++; + } + + _max_degree = graph_degree(ch->num_facets, facets, num_nbrs, degree); + if (_max_degree > max_degree) + return PTM_NO_ERROR; + + double normalized[PTM_MAX_POINTS][3]; + subtract_barycentre(num_nbrs + 1, points, normalized); + + int8_t code[2 * PTM_MAX_EDGES]; + int8_t colours[PTM_MAX_POINTS] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int8_t canonical_labelling[PTM_MAX_POINTS]; + uint64_t hash = 0; + ret = canonical_form_coloured(ch->num_facets, facets, num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); + if (ret != PTM_NO_ERROR) + return ret; + + if (flags & PTM_CHECK_DCUB) check_graphs(&structure_dcub, hash, canonical_labelling, normalized, res); + if (flags & PTM_CHECK_DHEX) check_graphs(&structure_dhex, hash, canonical_labelling, normalized, res); + + return PTM_NO_ERROR; +} + diff --git a/src/USER-PTM/structure_matcher.h b/src/USER-PTM/structure_matcher.h new file mode 100644 index 0000000000..25e80a94e1 --- /dev/null +++ b/src/USER-PTM/structure_matcher.h @@ -0,0 +1,21 @@ +#ifndef STRUCTURE_MATCHER_H +#define STRUCTURE_MATCHER_H + +#include "initialize_data.h" +#include "ptm_constants.h" + +typedef struct +{ + double rmsd; + double scale; + double q[4]; //rotation in quaternion form (rigid body transformation) + int8_t mapping[PTM_MAX_POINTS]; + const refdata_t* ref_struct; +} result_t; + +int match_general(const refdata_t* s, double (*ch_points)[3], double (*points)[3], convexhull_t* ch, result_t* res); +int match_fcc_hcp_ico(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); +int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); + +#endif + From 83b6d6ae960ce0e7f8edb32d95edb3540ae5f764 Mon Sep 17 00:00:00 2001 From: oywg11 Date: Wed, 12 Sep 2018 17:47:16 +0300 Subject: [PATCH 02/13] small modifications of potential #839 --- doc/src/pair_coul_shield.txt | 8 ++++- doc/src/pair_ilp_graphene_hbn.txt | 20 ++++++----- doc/src/pair_kolmogorov_crespi_full.txt | 34 +++++++++++-------- potentials/BNCH.ILP | 2 +- potentials/CH.KC | 4 +-- potentials/CH_taper.KC | 10 ++++++ src/USER-MISC/pair_ilp_graphene_hbn.cpp | 27 +++++++-------- src/USER-MISC/pair_kolmogorov_crespi_full.cpp | 27 +++++++-------- 8 files changed, 76 insertions(+), 56 deletions(-) create mode 100644 potentials/CH_taper.KC diff --git a/doc/src/pair_coul_shield.txt b/doc/src/pair_coul_shield.txt index 19f69688d5..517cb47740 100644 --- a/doc/src/pair_coul_shield.txt +++ b/doc/src/pair_coul_shield.txt @@ -38,7 +38,7 @@ charge and molecule ID information is included. Where Tap(r_ij) is the taper function which provides a continuous cutoff (up to third derivative) for inter-atomic separations larger than r_c -"(Maaravi)"_#Maaravi1. Here {lambda} is the shielding parameter that +"(Leven1)"_#Leven2, "(Leven2)"_#Leven3 and "(Maaravi)"_#Maaravi1. Here {lambda} is the shielding parameter that eliminates the short-range singularity of the classical mono-polar electrostatic interaction expression "(Maaravi)"_#Maaravi1. @@ -82,5 +82,11 @@ LAMMPS"_Section_start.html#start_2_3 section for more info. :line +:link(Leven2) +[(Leven)] I. Leven, I. Azuri, L. Kronik and O. Hod, J. Chem. Phys. 140, 104106 (2014). + +:link(Leven3) +[(Leven)] I. Leven et al, J. Chem.Theory Comput. 12, 2896-905 (2016). + :link(Maaravi1) [(Maaravi)] T. Maaravi et al, J. Phys. Chem. C 121, 22826-22835 (2017). diff --git a/doc/src/pair_ilp_graphene_hbn.txt b/doc/src/pair_ilp_graphene_hbn.txt index 127b8e9103..dd175b3b4f 100644 --- a/doc/src/pair_ilp_graphene_hbn.txt +++ b/doc/src/pair_ilp_graphene_hbn.txt @@ -31,7 +31,7 @@ pair_coeff 2 2 coul/shield 0.69 :pre [Description:] The {ilp/graphene/hbn} style computes the registry-dependent interlayer -potential (ILP) potential as described in "(Leven)"_#Leven and +potential (ILP) potential as described in "(Leven1)"_#Leven1, "(Leven2)"_#Leven and "(Maaravi)"_#Maaravi2. The normals are calculated in the way as described in "(Kolmogorov)"_#Kolmogorov2. @@ -40,7 +40,7 @@ in "(Kolmogorov)"_#Kolmogorov2. Where Tap(r_ij) is the taper function which provides a continuous cutoff (up to third derivative) for interatomic separations larger than r_c "(Maaravi)"_#Maaravi2. The definitons of each parameter in the above -equation can be found in "(Leven)"_#Leven and "(Maaravi)"_#Maaravi2. +equation can be found in "(Leven)"_#Leven1 and "(Maaravi)"_#Maaravi2. It is important to include all the pairs to build the neighbor list for calculating the normals. @@ -62,9 +62,10 @@ are fitted with taper function by setting the cutoff equal to 16.0 Angstrom. Using different cutoff or taper function should be careful. NOTE: Two new sets of parameters of ILP for two-dimensional hexagonal Materials are presented in "(Ouyang)"_#Ouyang. -These parameters provide a good description in both short- and long-range interaction regime. -While the old ILP parameters published in "(Leven)"_#Leven and "(Maaravi)"_#Maaravi2 are only suitable for long-range interaction regime. -This feature is essential for simulations in high pressure regime (i.e., interlayer distance smaller than the equilibrium distance). +These parameters provide a good description in both short- and long-range interaction regimes. +While the old ILP parameters published in "(Leven)"_#Leven and "(Maaravi)"_#Maaravi2 are +only suitable for long-range interaction regime. This feature is essential for simulations +in high pressure regime (i.e., the interlayer distance is smaller than the equilibrium distance). The benchmark tests and comparison of these parameters can be found in "(Ouyang)"_#Ouyang. This potential must be used in combination with hybrid/overlay. @@ -110,14 +111,17 @@ units, if your simulation does not use {metal} units. :line +:link(Leven1) +[(Leven)] I. Leven, I. Azuri, L. Kronik and O. Hod, J. Chem. Phys. 140, 104106 (2014). + :link(Leven) -[(Leven)] I. Leven et al, J. Chem.Theory Comput. 12, 2896-905 (2016) +[(Leven)] I. Leven et al, J. Chem.Theory Comput. 12, 2896-905 (2016). :link(Maaravi2) [(Maaravi)] T. Maaravi et al, J. Phys. Chem. C 121, 22826-22835 (2017). :link(Kolmogorov2) -[(Kolmogorov)] A. N. Kolmogorov, V. H. Crespi, Phys. Rev. B 71, 235415 (2005) +[(Kolmogorov)] A. N. Kolmogorov, V. H. Crespi, Phys. Rev. B 71, 235415 (2005). :link(Ouyang) -[(Ouyang)] W. Ouyang, D. Mandelli, M. Urbakh, O. Hod, arXiv:1806.09555 (2018). +[(Ouyang)] W. Ouyang, D. Mandelli, M. Urbakh and O. Hod, Nano Lett. 18, 6009-6016 (2018). diff --git a/doc/src/pair_kolmogorov_crespi_full.txt b/doc/src/pair_kolmogorov_crespi_full.txt index 10bb8a5224..09f0aaaed0 100644 --- a/doc/src/pair_kolmogorov_crespi_full.txt +++ b/doc/src/pair_kolmogorov_crespi_full.txt @@ -19,11 +19,11 @@ tap_flag = 0/1 to turn off/on the taper function pair_style hybrid/overlay kolmogorov/crespi/full 20.0 0 pair_coeff * * none -pair_coeff * * kolmogorov/crespi/full CC.KC C C :pre +pair_coeff * * kolmogorov/crespi/full CH.KC C C :pre -pair_style hybrid/overlay rebo kolmogorov/crespi/full 16.0 -pair_coeff * * rebo CH.airebo C C -pair_coeff * * kolmogorov/crespi/full CC.KC C C :pre +pair_style hybrid/overlay rebo kolmogorov/crespi/full 16.0 1 +pair_coeff * * rebo CH.airebo C H +pair_coeff * * kolmogorov/crespi/full CH_taper.KC C H :pre [Description:] @@ -38,24 +38,30 @@ forces and to include all the pairs to build the neighbor list for calculating the normals. Energies are shifted so that they go continuously to zero at the cutoff assuming that the exponential part of {Vij} (first term) decays sufficiently fast. This shift is achieved by -the last term in the equation for {Vij} above. +the last term in the equation for {Vij} above. This is essential only +when the tapper function is turned off. The formula of taper function +can be found in pair style "ilp/graphene/hbn"_pair_ilp_graphene_hbn.html. NOTE: This potential is intended for interactions between two different graphene layers. Therefore, to avoid interaction within the same layers, each layer should have a separate molecule id and is recommended to use "full" atom style in the data file. -The parameter file (e.g. CC.KC), is intended for use with {metal} +The parameter file (e.g. CH.KC), is intended for use with {metal} "units"_units.html, with energies in meV. Two additional parameters, {S}, and {rcut} are included in the parameter file. {S} is designed to facilitate scaling of energies. {rcut} is designed to build the neighbor list for calculating the normals for each atom pair. -NOTE: A new set of parameters of KC potential for hydrocarbons (CH.KC) is presented in "(Ouyang)"_#Ouyang. -The parameters in CH.KC provides a good description in both short- and long-range interaction regime. -While the original parameters (CC.KC) published in "(Kolmogorov)"_#Kolmogorov1 are only suitable for long-range interaction regime. -This feature is essential for simulations in high pressure regime (i.e., interlayer distance smaller than the equilibrium distance). -The benchmark tests and comparison of these parameters can be found in "(Ouyang)"_#Ouyang. +NOTE: Two new sets of parameters of KC potential for hydrocarbons, CH.KC (without the taper function) +and CH_taper.KC (with the taper function) are presented in "(Ouyang)"_#Ouyang1. +The energy for the KC potential with the taper function goes continuously to zero at the cutoff. +The parameters in both CH.KC and CH_taper.KC provide a good description in +both short- and long-range interaction regimes. While the original parameters (CC.KC) +published in "(Kolmogorov)"_#Kolmogorov1 are only suitable for long-range interaction regime. +This feature is essential for simulations in high pressure regime +(i.e., the interlayer distance is smaller than the equilibrium distance). +The benchmark tests and comparison of these parameters can be found in "(Ouyang)"_#Ouyang1. This potential must be used in combination with hybrid/overlay. Other interactions can be set to zero using pair_style {none}. @@ -81,7 +87,7 @@ LAMMPS"_Section_start.html#start_3 section for more info. This pair potential requires the newton setting to be {on} for pair interactions. -The CC.KC potential file provided with LAMMPS (see the potentials +The CH.KC potential file provided with LAMMPS (see the potentials folder) are parameterized for metal units. You can use this potential with any LAMMPS units, but you would need to create your own custom CC.KC potential file with all coefficients converted to the appropriate @@ -102,5 +108,5 @@ units. :link(Kolmogorov1) [(Kolmogorov)] A. N. Kolmogorov, V. H. Crespi, Phys. Rev. B 71, 235415 (2005) -:link(Ouyang) -[(Ouyang)] W. Ouyang, D. Mandelli, M. Urbakh, O. Hod, arXiv:1806.09555 (2018). +:link(Ouyang1) +[(Ouyang)] W. Ouyang, D. Mandelli, M. Urbakh and O. Hod, Nano Lett. 18, 6009-6016 (2018). diff --git a/potentials/BNCH.ILP b/potentials/BNCH.ILP index 3f38b5e35a..6ca56ca186 100644 --- a/potentials/BNCH.ILP +++ b/potentials/BNCH.ILP @@ -1,6 +1,6 @@ # Interlayer Potential (ILP) for graphene/graphene, graphene/hBN and hBN/hBN junctions # -# Cite as Wengen Ouyang,Davide Mandelli, Michael Urbakh, Oded Hod, arXiv:1806.09555 (2018). +# Cite as W. Ouyang, D. Mandelli, M. Urbakh and O. Hod, Nano Letters 18, 6009-6016 (2018). # # ----------------- Repulsion Potential ------------------++++++++++++++ Vdw Potential ++++++++++++++++************ # beta(A) alpha delta(A) epsilon(meV) C(meV) d sR reff(A) C6(meV*A^6) S rcut diff --git a/potentials/CH.KC b/potentials/CH.KC index 2005472395..1b4f7503ea 100644 --- a/potentials/CH.KC +++ b/potentials/CH.KC @@ -1,6 +1,6 @@ -# Refined parameters for Kolmogorov-Crespi Potential +# Refined parameters for Kolmogorov-Crespi Potential without taper function # -# Cite as Wengen Ouyang,Davide Mandelli, Michael Urbakh, Oded Hod, arXiv:1806.09555 (2018). +# Cite as W. Ouyang, D. Mandelli, M. Urbakh and O. Hod, Nano Letters 18, 6009-6016 (2018). # # z0 C0 C2 C4 C delta lambda A S rcut C C 3.328819 21.847167 12.060173 4.711099 6.678908e-4 0.7718101 3.143921 12.660270 1.0 2.0 diff --git a/potentials/CH_taper.KC b/potentials/CH_taper.KC new file mode 100644 index 0000000000..0f08b2e6dd --- /dev/null +++ b/potentials/CH_taper.KC @@ -0,0 +1,10 @@ +# Refined parameters for Kolmogorov-Crespi Potential with taper function +# +# Cite as W. Ouyang, D. Mandelli, M. Urbakh and O. Hod, Nano Letters 18, 6009-6016 (2018). +# +# z0 C0 C2 C4 C delta lambda A S rcut +C C 3.416084 20.021583 10.9055107 4.2756354 1.0010836E-2 0.8447122 2.9360584 14.3132588 1.0 2.0 +C H 2.849054 72.557245 1.0164169E-2 65.923312 8.7962504E-5 0.3349237 3.0402632 14.7533201 1.0 1.5 +H H 2.187478 3.915802E-5 5.0896431E-5 3.6657827 1.5373722446 0.9633581 0.4249989 1.570737E-4 1.0 1.2 +H C 2.849054 72.557245 1.0164169E-2 65.923312 8.7962504E-5 0.3349237 3.0402632 14.7533201 1.0 2.2 + diff --git a/src/USER-MISC/pair_ilp_graphene_hbn.cpp b/src/USER-MISC/pair_ilp_graphene_hbn.cpp index 30ee2e7a5a..7c637e4faf 100644 --- a/src/USER-MISC/pair_ilp_graphene_hbn.cpp +++ b/src/USER-MISC/pair_ilp_graphene_hbn.cpp @@ -249,11 +249,9 @@ void PairILPGrapheneHBN::compute(int eflag, int vflag) f[i][0] += fkcx - fprod1[0]*Tap; f[i][1] += fkcy - fprod1[1]*Tap; f[i][2] += fkcz - fprod1[2]*Tap; - if (newton_pair || j < nlocal) { - f[j][0] -= fkcx + fprod2[0]*Tap; - f[j][1] -= fkcy + fprod2[1]*Tap; - f[j][2] -= fkcz + fprod2[2]*Tap; - } + f[j][0] -= fkcx + fprod2[0]*Tap; + f[j][1] -= fkcy + fprod2[1]*Tap; + f[j][2] -= fkcz + fprod2[2]*Tap; // calculate the forces acted on the neighbors of atom i from atom j ILP_neighs_i = ILP_firstneigh[i]; @@ -274,15 +272,13 @@ void PairILPGrapheneHBN::compute(int eflag, int vflag) for (ll = 0; ll < ILP_numneigh[j]; ll++) { l = ILP_neighs_j[ll]; if (l == j) continue; - if (newton_pair || l < nlocal) { - // derivatives of the product of rji and nj respect to rl, l=0,1,2, where atom l is the neighbors of atom j - dprodnorm2[0] = dnormal[0][0][ll][j]*delx + dnormal[1][0][ll][j]*dely + dnormal[2][0][ll][j]*delz; - dprodnorm2[1] = dnormal[0][1][ll][j]*delx + dnormal[1][1][ll][j]*dely + dnormal[2][1][ll][j]*delz; - dprodnorm2[2] = dnormal[0][2][ll][j]*delx + dnormal[1][2][ll][j]*dely + dnormal[2][2][ll][j]*delz; - f[l][0] += (-prodnorm2*dprodnorm2[0]*fpair2)*Tap; - f[l][1] += (-prodnorm2*dprodnorm2[1]*fpair2)*Tap; - f[l][2] += (-prodnorm2*dprodnorm2[2]*fpair2)*Tap; - } + // derivatives of the product of rji and nj respect to rl, l=0,1,2, where atom l is the neighbors of atom j + dprodnorm2[0] = dnormal[0][0][ll][j]*delx + dnormal[1][0][ll][j]*dely + dnormal[2][0][ll][j]*delz; + dprodnorm2[1] = dnormal[0][1][ll][j]*delx + dnormal[1][1][ll][j]*dely + dnormal[2][1][ll][j]*delz; + dprodnorm2[2] = dnormal[0][2][ll][j]*delx + dnormal[1][2][ll][j]*dely + dnormal[2][2][ll][j]*delz; + f[l][0] += (-prodnorm2*dprodnorm2[0]*fpair2)*Tap; + f[l][1] += (-prodnorm2*dprodnorm2[1]*fpair2)*Tap; + f[l][2] += (-prodnorm2*dprodnorm2[2]*fpair2)*Tap; } if (eflag) { @@ -729,7 +725,8 @@ void PairILPGrapheneHBN::ILP_neigh() ILP_firstneigh[i] = neighptr; ILP_numneigh[i] = n; - if (n > 3) error->all(FLERR,"There are too many neighbors for some atoms, please reduce the cutoff for normals"); + if (n == 0) error->all(FLERR,"Could not build neighbor list to calculate normals, please check your configuration"); + if (n > 3) error->all(FLERR,"There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); diff --git a/src/USER-MISC/pair_kolmogorov_crespi_full.cpp b/src/USER-MISC/pair_kolmogorov_crespi_full.cpp index be0e81d48d..93a2376c33 100644 --- a/src/USER-MISC/pair_kolmogorov_crespi_full.cpp +++ b/src/USER-MISC/pair_kolmogorov_crespi_full.cpp @@ -249,11 +249,9 @@ void PairKolmogorovCrespiFull::compute(int eflag, int vflag) f[i][0] += fkcx - fprod1[0]*Tap; f[i][1] += fkcy - fprod1[1]*Tap; f[i][2] += fkcz - fprod1[2]*Tap; - if (newton_pair || j < nlocal) { - f[j][0] -= fkcx + fprod2[0]*Tap; - f[j][1] -= fkcy + fprod2[1]*Tap; - f[j][2] -= fkcz + fprod2[2]*Tap; - } + f[j][0] -= fkcx + fprod2[0]*Tap; + f[j][1] -= fkcy + fprod2[1]*Tap; + f[j][2] -= fkcz + fprod2[2]*Tap; // calculate the forces acted on the neighbors of atom i from atom j KC_neighs_i = KC_firstneigh[i]; @@ -274,15 +272,13 @@ void PairKolmogorovCrespiFull::compute(int eflag, int vflag) for (ll = 0; ll < KC_numneigh[j]; ll++) { l = KC_neighs_j[ll]; if (l == j) continue; - if (newton_pair || l < nlocal) { - // derivatives of the product of rji and nj respect to rl, l=0,1,2, where atom l is the neighbors of atom j - dprodnorm2[0] = dnormal[0][0][ll][j]*delx + dnormal[1][0][ll][j]*dely + dnormal[2][0][ll][j]*delz; - dprodnorm2[1] = dnormal[0][1][ll][j]*delx + dnormal[1][1][ll][j]*dely + dnormal[2][1][ll][j]*delz; - dprodnorm2[2] = dnormal[0][2][ll][j]*delx + dnormal[1][2][ll][j]*dely + dnormal[2][2][ll][j]*delz; - f[l][0] += (-prodnorm2*dprodnorm2[0]*fpair2)*Tap; - f[l][1] += (-prodnorm2*dprodnorm2[1]*fpair2)*Tap; - f[l][2] += (-prodnorm2*dprodnorm2[2]*fpair2)*Tap; - } + // derivatives of the product of rji and nj respect to rl, l=0,1,2, where atom l is the neighbors of atom j + dprodnorm2[0] = dnormal[0][0][ll][j]*delx + dnormal[1][0][ll][j]*dely + dnormal[2][0][ll][j]*delz; + dprodnorm2[1] = dnormal[0][1][ll][j]*delx + dnormal[1][1][ll][j]*dely + dnormal[2][1][ll][j]*delz; + dprodnorm2[2] = dnormal[0][2][ll][j]*delx + dnormal[1][2][ll][j]*dely + dnormal[2][2][ll][j]*delz; + f[l][0] += (-prodnorm2*dprodnorm2[0]*fpair2)*Tap; + f[l][1] += (-prodnorm2*dprodnorm2[1]*fpair2)*Tap; + f[l][2] += (-prodnorm2*dprodnorm2[2]*fpair2)*Tap; } if (eflag) { @@ -734,7 +730,8 @@ void PairKolmogorovCrespiFull::KC_neigh() KC_firstneigh[i] = neighptr; KC_numneigh[i] = n; - if (n > 3) error->all(FLERR,"There are too many neighbors for some atoms, please reduce the cutoff for normals"); + if (n == 0) error->all(FLERR,"Could not build neighbor list to calculate normals, please check your configuration"); + if (n > 3) error->all(FLERR,"There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); From 01beaf38a1162c0d81ad9591b490782b73997179 Mon Sep 17 00:00:00 2001 From: oywg11 Date: Wed, 12 Sep 2018 21:51:57 +0300 Subject: [PATCH 03/13] small modifications for potential #839 --- doc/src/pair_coul_shield.txt | 10 +++++----- doc/src/pair_ilp_graphene_hbn.txt | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/src/pair_coul_shield.txt b/doc/src/pair_coul_shield.txt index 517cb47740..c6eb7bf7a1 100644 --- a/doc/src/pair_coul_shield.txt +++ b/doc/src/pair_coul_shield.txt @@ -38,7 +38,7 @@ charge and molecule ID information is included. Where Tap(r_ij) is the taper function which provides a continuous cutoff (up to third derivative) for inter-atomic separations larger than r_c -"(Leven1)"_#Leven2, "(Leven2)"_#Leven3 and "(Maaravi)"_#Maaravi1. Here {lambda} is the shielding parameter that +"(Leven1)"_#Leven3, "(Leven2)"_#Leven4 and "(Maaravi)"_#Maaravi1. Here {lambda} is the shielding parameter that eliminates the short-range singularity of the classical mono-polar electrostatic interaction expression "(Maaravi)"_#Maaravi1. @@ -82,11 +82,11 @@ LAMMPS"_Section_start.html#start_2_3 section for more info. :line -:link(Leven2) -[(Leven)] I. Leven, I. Azuri, L. Kronik and O. Hod, J. Chem. Phys. 140, 104106 (2014). - :link(Leven3) -[(Leven)] I. Leven et al, J. Chem.Theory Comput. 12, 2896-905 (2016). +[(Leven1)] I. Leven, I. Azuri, L. Kronik and O. Hod, J. Chem. Phys. 140, 104106 (2014). + +:link(Leven4) +[(Leven2)] I. Leven et al, J. Chem.Theory Comput. 12, 2896-905 (2016). :link(Maaravi1) [(Maaravi)] T. Maaravi et al, J. Phys. Chem. C 121, 22826-22835 (2017). diff --git a/doc/src/pair_ilp_graphene_hbn.txt b/doc/src/pair_ilp_graphene_hbn.txt index dd175b3b4f..d5d8a29fbe 100644 --- a/doc/src/pair_ilp_graphene_hbn.txt +++ b/doc/src/pair_ilp_graphene_hbn.txt @@ -31,7 +31,7 @@ pair_coeff 2 2 coul/shield 0.69 :pre [Description:] The {ilp/graphene/hbn} style computes the registry-dependent interlayer -potential (ILP) potential as described in "(Leven1)"_#Leven1, "(Leven2)"_#Leven and +potential (ILP) potential as described in "(Leven1)"_#Leven1, "(Leven2)"_#Leven2 and "(Maaravi)"_#Maaravi2. The normals are calculated in the way as described in "(Kolmogorov)"_#Kolmogorov2. @@ -40,7 +40,7 @@ in "(Kolmogorov)"_#Kolmogorov2. Where Tap(r_ij) is the taper function which provides a continuous cutoff (up to third derivative) for interatomic separations larger than r_c "(Maaravi)"_#Maaravi2. The definitons of each parameter in the above -equation can be found in "(Leven)"_#Leven1 and "(Maaravi)"_#Maaravi2. +equation can be found in "(Leven1)"_#Leven1 and "(Maaravi)"_#Maaravi2. It is important to include all the pairs to build the neighbor list for calculating the normals. @@ -112,10 +112,10 @@ units, if your simulation does not use {metal} units. :line :link(Leven1) -[(Leven)] I. Leven, I. Azuri, L. Kronik and O. Hod, J. Chem. Phys. 140, 104106 (2014). +[(Leven1)] I. Leven, I. Azuri, L. Kronik and O. Hod, J. Chem. Phys. 140, 104106 (2014). -:link(Leven) -[(Leven)] I. Leven et al, J. Chem.Theory Comput. 12, 2896-905 (2016). +:link(Leven2) +[(Leven2)] I. Leven et al, J. Chem.Theory Comput. 12, 2896-905 (2016). :link(Maaravi2) [(Maaravi)] T. Maaravi et al, J. Phys. Chem. C 121, 22826-22835 (2017). From c705e8d0e6a3b1a739f2ddf6cd1ee40a3241d40a Mon Sep 17 00:00:00 2001 From: pmla Date: Wed, 19 Sep 2018 20:46:48 -0400 Subject: [PATCH 04/13] renamed files for LAMMPS build system compatibility --- src/PTM/compute_ptm_atom.cpp | 307 ++++ src/PTM/compute_ptm_atom.h | 48 + src/PTM/ptm_alloy_types.cpp | 101 ++ src/PTM/ptm_alloy_types.h | 9 + src/PTM/ptm_canonical_coloured.cpp | 167 ++ src/PTM/ptm_canonical_coloured.h | 9 + src/PTM/ptm_constants.h | 174 ++ src/PTM/ptm_convex_hull_incremental.cpp | 363 ++++ src/PTM/ptm_convex_hull_incremental.h | 27 + src/PTM/ptm_deformation_gradient.cpp | 37 + src/PTM/ptm_deformation_gradient.h | 142 ++ src/PTM/ptm_functions.h | 27 + src/PTM/ptm_fundamental_mappings.h | 180 ++ src/PTM/ptm_graph_data.cpp | 2059 +++++++++++++++++++++++ src/PTM/ptm_graph_data.h | 37 + src/PTM/ptm_graph_tools.cpp | 52 + src/PTM/ptm_graph_tools.h | 11 + src/PTM/ptm_index.cpp | 218 +++ src/PTM/ptm_initialize_data.cpp | 71 + src/PTM/ptm_initialize_data.h | 61 + src/PTM/ptm_neighbour_ordering.cpp | 203 +++ src/PTM/ptm_neighbour_ordering.h | 13 + src/PTM/ptm_normalize_vertices.cpp | 55 + src/PTM/ptm_normalize_vertices.h | 8 + src/PTM/ptm_polar.cpp | 337 ++++ src/PTM/ptm_polar.h | 12 + src/PTM/ptm_quat.cpp | 396 +++++ src/PTM/ptm_quat.h | 32 + src/PTM/ptm_structure_matcher.cpp | 294 ++++ src/PTM/ptm_structure_matcher.h | 21 + src/PTM/ptm_voronoi_cell.cpp | 1368 +++++++++++++++ src/PTM/ptm_voronoi_cell.h | 324 ++++ src/PTM/ptm_voronoi_config.h | 129 ++ 33 files changed, 7292 insertions(+) create mode 100644 src/PTM/compute_ptm_atom.cpp create mode 100644 src/PTM/compute_ptm_atom.h create mode 100644 src/PTM/ptm_alloy_types.cpp create mode 100644 src/PTM/ptm_alloy_types.h create mode 100644 src/PTM/ptm_canonical_coloured.cpp create mode 100644 src/PTM/ptm_canonical_coloured.h create mode 100644 src/PTM/ptm_constants.h create mode 100644 src/PTM/ptm_convex_hull_incremental.cpp create mode 100644 src/PTM/ptm_convex_hull_incremental.h create mode 100644 src/PTM/ptm_deformation_gradient.cpp create mode 100644 src/PTM/ptm_deformation_gradient.h create mode 100644 src/PTM/ptm_functions.h create mode 100644 src/PTM/ptm_fundamental_mappings.h create mode 100644 src/PTM/ptm_graph_data.cpp create mode 100644 src/PTM/ptm_graph_data.h create mode 100644 src/PTM/ptm_graph_tools.cpp create mode 100644 src/PTM/ptm_graph_tools.h create mode 100644 src/PTM/ptm_index.cpp create mode 100644 src/PTM/ptm_initialize_data.cpp create mode 100644 src/PTM/ptm_initialize_data.h create mode 100644 src/PTM/ptm_neighbour_ordering.cpp create mode 100644 src/PTM/ptm_neighbour_ordering.h create mode 100644 src/PTM/ptm_normalize_vertices.cpp create mode 100644 src/PTM/ptm_normalize_vertices.h create mode 100644 src/PTM/ptm_polar.cpp create mode 100644 src/PTM/ptm_polar.h create mode 100644 src/PTM/ptm_quat.cpp create mode 100644 src/PTM/ptm_quat.h create mode 100644 src/PTM/ptm_structure_matcher.cpp create mode 100644 src/PTM/ptm_structure_matcher.h create mode 100644 src/PTM/ptm_voronoi_cell.cpp create mode 100644 src/PTM/ptm_voronoi_cell.h create mode 100644 src/PTM/ptm_voronoi_config.h diff --git a/src/PTM/compute_ptm_atom.cpp b/src/PTM/compute_ptm_atom.cpp new file mode 100644 index 0000000000..b6b4a9786c --- /dev/null +++ b/src/PTM/compute_ptm_atom.cpp @@ -0,0 +1,307 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed +under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: PM Larsen (MIT) +------------------------------------------------------------------------- */ + +#include +#include +#include +#include + +#include "atom.h" +#include "comm.h" +#include "compute_ptm_atom.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "modify.h" +#include "neigh_list.h" +#include "neigh_request.h" +#include "neighbor.h" +#include "pair.h" +#include "update.h" + +#include "ptm_functions.h" + +#define MAX_NEIGHBORS 30 +#define NUM_COLUMNS 7 +#define UNKNOWN 0 +#define OTHER 8 + +using namespace LAMMPS_NS; + +static const char cite_user_ptm_package[] = + "USER-PTM package:\n\n" + "@Article{larsen2016ptm,\n" + " author={Larsen, Peter Mahler and Schmidt, S{\o}ren and Schi{\o}tz, " + "Jakob},\n" + " title={Robust structural identification via polyhedral template " + "matching},\n" + " journal={Modelling~Simul.~Mater.~Sci.~Eng.},\n" + " year={2016},\n" + " number={5},\n" + " volume={24},\n" + " pages={055007},\n" + " DOI = {10.1088/0965-0393/24/5/055007}" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +ComputePTMAtom::ComputePTMAtom(LAMMPS *lmp, int narg, char **arg) + : Compute(lmp, narg, arg), list(NULL), output(NULL) { + if (narg != 5) + error->all(FLERR, "Illegal compute ptm/atom command"); + + char *structures = arg[3]; + char *ptr = structures; + + const char *strings[] = {"fcc", "hcp", "bcc", "ico", "sc", + "dcub", "dhex", "all", "default"}; + int32_t flags[] = { + PTM_CHECK_FCC, + PTM_CHECK_HCP, + PTM_CHECK_BCC, + PTM_CHECK_ICO, + PTM_CHECK_SC, + PTM_CHECK_DCUB, + PTM_CHECK_DHEX, + PTM_CHECK_ALL, + PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_BCC | PTM_CHECK_ICO}; + + input_flags = 0; + while (*ptr != '\0') { + + bool found = false; + for (int i = 0; i < 9; i++) { + int len = strlen(strings[i]); + if (strncmp(ptr, strings[i], len) == 0) { + input_flags |= flags[i]; + ptr += len; + found = true; + break; + } + } + + if (!found) + error->all(FLERR, + "Illegal compute ptm/atom command (invalid structure type)"); + + if (*ptr == '\0') + break; + + if (*ptr != '-') + error->all(FLERR, + "Illegal compute ptm/atom command (invalid structure type)"); + + ptr++; + } + + double threshold = force->numeric(FLERR, arg[4]); + if (threshold < 0.0) + error->all(FLERR, + "Illegal compute ptm/atom command (threshold is negative)"); + rmsd_threshold = threshold; + if (rmsd_threshold == 0) + rmsd_threshold = INFINITY; + + peratom_flag = 1; + size_peratom_cols = NUM_COLUMNS; + create_attribute = 1; + nmax = 0; +} + +/* ---------------------------------------------------------------------- */ + +ComputePTMAtom::~ComputePTMAtom() { memory->destroy(output); } + +/* ---------------------------------------------------------------------- */ + +void ComputePTMAtom::init() { + if (force->pair == NULL) + error->all(FLERR, "Compute ptm/atom requires a pair style be defined"); + + int count = 0; + for (int i = 0; i < modify->ncompute; i++) + if (strcmp(modify->compute[i]->style, "ptm/atom") == 0) + count++; + if (count > 1 && comm->me == 0) + error->warning(FLERR, "More than one compute ptm/atom defined"); + + // need an occasional full neighbor list + + int irequest = neighbor->request(this, instance_me); + neighbor->requests[irequest]->pair = 0; + neighbor->requests[irequest]->compute = 1; + neighbor->requests[irequest]->half = 0; + neighbor->requests[irequest]->full = 1; + neighbor->requests[irequest]->occasional = 1; +} + +/* ---------------------------------------------------------------------- */ + +void ComputePTMAtom::init_list(int id, NeighList *ptr) { list = ptr; } + +/* ---------------------------------------------------------------------- */ + +typedef struct { + int index; + double d; +} ptmnbr_t; + +static bool sorthelper_compare(ptmnbr_t const &a, ptmnbr_t const &b) { + return a.d < b.d; +} + +static int get_neighbors(double *pos, int jnum, int *jlist, double **x, + double (*nbr)[3]) { + + ptmnbr_t *nbr_order = new ptmnbr_t[jnum]; + + for (int jj = 0; jj < jnum; jj++) { + int j = jlist[jj]; + j &= NEIGHMASK; + + double dx = pos[0] - x[j][0]; + double dy = pos[1] - x[j][1]; + double dz = pos[2] - x[j][2]; + double rsq = dx * dx + dy * dy + dz * dz; + + nbr_order[jj].index = j; + nbr_order[jj].d = rsq; + } + + std::sort(nbr_order, nbr_order + jnum, &sorthelper_compare); + int num_nbrs = std::min(MAX_NEIGHBORS, jnum); + + nbr[0][0] = nbr[0][1] = nbr[0][2] = 0; + for (int jj = 0; jj < num_nbrs; jj++) { + + int j = nbr_order[jj].index; + nbr[jj + 1][0] = x[j][0] - pos[0]; + nbr[jj + 1][1] = x[j][1] - pos[1]; + nbr[jj + 1][2] = x[j][2] - pos[2]; + } + + delete[] nbr_order; + return num_nbrs; +} + +void ComputePTMAtom::compute_peratom() { + // PTM global initialization. If already initialized this function does + // nothing. + ptm_initialize_global(); + + // initialize PTM local storage + ptm_local_handle_t local_handle = ptm_initialize_local(); + + invoked_peratom = update->ntimestep; + + // grow arrays if necessary + if (atom->nmax > nmax) { + memory->destroy(output); + nmax = atom->nmax; + + memory->create(output, nmax, NUM_COLUMNS, "ptm:ptm_output"); + array_atom = output; + } + + // invoke full neighbor list (will copy or build if necessary) + neighbor->build_one(list); + + int inum = list->inum; + int *ilist = list->ilist; + int *numneigh = list->numneigh; + int **firstneigh = list->firstneigh; + + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int ii = 0; ii < inum; ii++) { + + int i = ilist[ii]; + output[i][0] = UNKNOWN; + if (!(mask[i] & groupbit)) + continue; + + double *pos = x[i]; + + int *jlist = firstneigh[i]; + int jnum = numneigh[i]; + if (jnum <= 0) + continue; + + // get neighbours ordered by increasing distance + double nbr[MAX_NEIGHBORS + 1][3]; + int num_nbrs = get_neighbors(pos, jnum, jlist, x, nbr); + + // check that we have enough neighbours for the desired structure types + int32_t flags = 0; + if (num_nbrs >= PTM_NUM_NBRS_SC && (input_flags & PTM_CHECK_SC)) + flags |= PTM_CHECK_SC; + if (num_nbrs >= PTM_NUM_NBRS_FCC && (input_flags & PTM_CHECK_FCC)) + flags |= PTM_CHECK_FCC; + if (num_nbrs >= PTM_NUM_NBRS_HCP && (input_flags & PTM_CHECK_HCP)) + flags |= PTM_CHECK_HCP; + if (num_nbrs >= PTM_NUM_NBRS_ICO && (input_flags & PTM_CHECK_ICO)) + flags |= PTM_CHECK_ICO; + if (num_nbrs >= PTM_NUM_NBRS_BCC && (input_flags & PTM_CHECK_BCC)) + flags |= PTM_CHECK_BCC; + if (num_nbrs >= PTM_NUM_NBRS_DCUB && (input_flags & PTM_CHECK_DCUB)) + flags |= PTM_CHECK_DCUB; + if (num_nbrs >= PTM_NUM_NBRS_DHEX && (input_flags & PTM_CHECK_DHEX)) + flags |= PTM_CHECK_DHEX; + + // now run PTM + int8_t mapping[MAX_NEIGHBORS + 1]; + int32_t type, alloy_type; + double scale, rmsd, interatomic_distance, lattice_constant; + double q[4], F[9], F_res[3], U[9], P[9]; + ptm_index(local_handle, flags, num_nbrs + 1, nbr, NULL, true, &type, + &alloy_type, &scale, &rmsd, q, F, F_res, U, P, mapping, + &interatomic_distance, &lattice_constant); + + if (rmsd > rmsd_threshold) { + type = PTM_MATCH_NONE; + } + + // printf("%d type=%d rmsd=%f\n", i, type, rmsd); + + if (type == PTM_MATCH_NONE) + type = OTHER; + + output[i][0] = type; + output[i][1] = rmsd; + output[i][2] = interatomic_distance; + output[i][3] = q[0]; + output[i][4] = q[1]; + output[i][5] = q[2]; + output[i][6] = q[3]; + } + + // printf("finished ptm analysis\n"); + ptm_uninitialize_local(local_handle); +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based array +------------------------------------------------------------------------- */ + +double ComputePTMAtom::memory_usage() { + double bytes = nmax * NUM_COLUMNS * sizeof(double); + bytes += nmax * sizeof(double); + return bytes; +} diff --git a/src/PTM/compute_ptm_atom.h b/src/PTM/compute_ptm_atom.h new file mode 100644 index 0000000000..5c10e0c443 --- /dev/null +++ b/src/PTM/compute_ptm_atom.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef COMPUTE_CLASS + +ComputeStyle(ptm/atom,ComputePTMAtom) + +#else + +#ifndef LMP_COMPUTE_PTM_ATOM_H +#define LMP_COMPUTE_PTM_ATOM_H + +#include "compute.h" + +namespace LAMMPS_NS { + +class ComputePTMAtom : public Compute { + public: + ComputePTMAtom(class LAMMPS *, int, char **); + ~ComputePTMAtom(); + void init(); + void init_list(int, class NeighList *); + void compute_peratom(); + double memory_usage(); + + private: + int nmax; + int32_t input_flags; + double rmsd_threshold; + class NeighList *list; + double **output; +}; + +} + +#endif +#endif + diff --git a/src/PTM/ptm_alloy_types.cpp b/src/PTM/ptm_alloy_types.cpp new file mode 100644 index 0000000000..e14d06db99 --- /dev/null +++ b/src/PTM/ptm_alloy_types.cpp @@ -0,0 +1,101 @@ +#include +#include "ptm_constants.h" +#include "ptm_initialize_data.h" + + +#define NUM_ALLOY_TYPES 3 +static uint32_t typedata[NUM_ALLOY_TYPES][3] = { + {PTM_MATCH_FCC, PTM_ALLOY_L10, 0x000001fe}, + {PTM_MATCH_FCC, PTM_ALLOY_L12_CU, 0x0000001e}, + {PTM_MATCH_FCC, PTM_ALLOY_L12_AU, 0x00001ffe}, +}; + +static bool test_pure(int num_nbrs, int32_t* numbers) +{ + for (int i=1;inum_nbrs+1;i++) + binary[i] = numbers[mapping[i]] == numbers[0] ? 0 : 1; + + for (int i=1;inum_nbrs+1;i++) + if (binary[i] != binary[0]) + return false; + + return true; +} + +static int32_t canonical_alloy_representation(const refdata_t* ref, int8_t* mapping, int32_t* numbers) +{ + int8_t binary[PTM_MAX_POINTS]; + for (int i=0;inum_nbrs+1;i++) + binary[i] = numbers[mapping[i]] == numbers[0] ? 0 : 1; + + int8_t temp[PTM_MAX_POINTS]; + uint32_t best = 0xFFFFFFFF; + for (int j=0;jnum_mappings;j++) + { + for (int i=0;inum_nbrs+1;i++) + temp[ref->mapping[j][i]] = binary[i]; + + uint32_t code = 0; + for (int i=0;inum_nbrs+1;i++) + code |= (temp[i] << i); + + best = std::min(best, code); + } + + return best; +} + +int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers) +{ + if (test_pure(ref->num_nbrs, numbers)) + return PTM_ALLOY_PURE; + + if (!test_binary(ref->num_nbrs, numbers)) + return PTM_ALLOY_NONE; + + uint32_t code = canonical_alloy_representation(ref, mapping, numbers); + for (int i=0;itype == typedata[i][0] && code == typedata[i][2]) + return typedata[i][1]; + + if (ref->type == PTM_MATCH_BCC) + if (test_shell_structure(ref, mapping, numbers, 8)) + return PTM_ALLOY_B2; + + if (ref->type == PTM_MATCH_DCUB || ref->type == PTM_MATCH_DHEX) + if (test_shell_structure(ref, mapping, numbers, 4)) + return PTM_ALLOY_SIC; + + return PTM_ALLOY_NONE; +} + diff --git a/src/PTM/ptm_alloy_types.h b/src/PTM/ptm_alloy_types.h new file mode 100644 index 0000000000..6ea6ed1b8a --- /dev/null +++ b/src/PTM/ptm_alloy_types.h @@ -0,0 +1,9 @@ +#ifndef PTM_ALLOY_TYPES_H +#define PTM_ALLOY_TYPES_H + +#include "ptm_initialize_data.h" + +int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers); + +#endif + diff --git a/src/PTM/ptm_canonical_coloured.cpp b/src/PTM/ptm_canonical_coloured.cpp new file mode 100644 index 0000000000..551f52d7e4 --- /dev/null +++ b/src/PTM/ptm_canonical_coloured.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include "ptm_graph_tools.h" +#include "ptm_constants.h" + + +static bool weinberg_coloured(int num_nodes, int num_edges, int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS], int8_t* colours, int8_t* best_code, int8_t* canonical_labelling, int a, int b) +{ + bool m[PTM_MAX_NBRS][PTM_MAX_NBRS]; + memset(m, 0, sizeof(bool) * PTM_MAX_NBRS * PTM_MAX_NBRS); + + int8_t index[PTM_MAX_NBRS]; + memset(index, -1, sizeof(int8_t) * PTM_MAX_NBRS); + + + int n = 0; + index[a] = colours[a] * num_nodes + n++; + if (index[a] > best_code[0]) + return false; + + bool winning = false; + if (index[a] < best_code[0]) + { + best_code[0] = index[a]; + winning = true; + } + + int c = -1; + for (int it=1;it<2*num_edges;it++) + { + bool newvertex = index[b] == -1; + + if (newvertex) + index[b] = colours[b] * num_nodes + n++; + + if (!winning && index[b] > best_code[it]) + return false; + + if (winning || index[b] < best_code[it]) + { + winning = true; + best_code[it] = index[b]; + } + + if (newvertex) + { + //When a new vertex is reached, take the right-most edge + //relative to the edge on which the vertex is reached. + + c = common[a][b]; + } + else if (m[b][a] == false) + { + //When an old vertex is reached on a new path, go back + //in the opposite direction. + + c = a; + } + else + { + //When an old vertex is reached on an old path, leave the + //vertex on the right-most edge that has not previously + //been traversed in that direction. + + c = common[a][b]; + while (m[b][c] == true) + c = common[c][b]; + } + + m[a][b] = true; + a = b; + b = c; + } + + if (winning) + { + memcpy(canonical_labelling, index, sizeof(int8_t) * num_nodes); + return true; + } + + return false; +} + +int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree, int8_t* colours, int8_t* canonical_labelling, int8_t* best_code, uint64_t* p_hash) +{ + int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS] = {{0}}; + int num_edges = 3 * num_facets / 2; + if (!build_facet_map(num_facets, facets, common)) + return -1; + + memset(best_code, SCHAR_MAX, sizeof(int8_t) * 2 * PTM_MAX_EDGES); + + bool equal = true; + for (int i = 1;i=0;i--) + canonical_labelling[i+1] = (canonical_labelling[i] % num_nodes) + 1; + canonical_labelling[0] = 0; + + uint64_t hash = 0; + for (int i = 0;i<2 * num_edges;i++) + { + uint64_t e = best_code[i]; + e += i % 8; + e &= 0xF; + e <<= (4 * i) % 64; + hash ^= e; + } + + *p_hash = hash; + return PTM_NO_ERROR; +} + diff --git a/src/PTM/ptm_canonical_coloured.h b/src/PTM/ptm_canonical_coloured.h new file mode 100644 index 0000000000..e71bb08bfc --- /dev/null +++ b/src/PTM/ptm_canonical_coloured.h @@ -0,0 +1,9 @@ +#ifndef PTM_CANONICAL_COLOURED_H +#define PTM_CANONICAL_COLOURED_H + +#include + +int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree, int8_t* colours, int8_t* canonical_labelling, int8_t* best_code, uint64_t* p_hash); + +#endif + diff --git a/src/PTM/ptm_constants.h b/src/PTM/ptm_constants.h new file mode 100644 index 0000000000..f868f51e84 --- /dev/null +++ b/src/PTM/ptm_constants.h @@ -0,0 +1,174 @@ +#ifndef PTM_CONSTANTS_H +#define PTM_CONSTANTS_H + +//------------------------------------ +// definitions +//------------------------------------ +#define PTM_NO_ERROR 0 + + +#define PTM_CHECK_FCC (1 << 0) +#define PTM_CHECK_HCP (1 << 1) +#define PTM_CHECK_BCC (1 << 2) +#define PTM_CHECK_ICO (1 << 3) +#define PTM_CHECK_SC (1 << 4) +#define PTM_CHECK_DCUB (1 << 5) +#define PTM_CHECK_DHEX (1 << 6) +#define PTM_CHECK_NONDIAMOND (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC) +#define PTM_CHECK_ALL (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC | PTM_CHECK_DCUB | PTM_CHECK_DHEX) + +#define PTM_MATCH_NONE 0 +#define PTM_MATCH_FCC 1 +#define PTM_MATCH_HCP 2 +#define PTM_MATCH_BCC 3 +#define PTM_MATCH_ICO 4 +#define PTM_MATCH_SC 5 +#define PTM_MATCH_DCUB 6 +#define PTM_MATCH_DHEX 7 + +#define PTM_ALLOY_NONE 0 +#define PTM_ALLOY_PURE 1 +#define PTM_ALLOY_L10 2 +#define PTM_ALLOY_L12_CU 3 +#define PTM_ALLOY_L12_AU 4 +#define PTM_ALLOY_B2 5 +#define PTM_ALLOY_SIC 6 + + +#define PTM_MAX_INPUT_POINTS 35 +#define PTM_MAX_NBRS 16 +#define PTM_MAX_POINTS (PTM_MAX_NBRS + 1) +#define PTM_MAX_FACETS 28 //2 * PTM_MAX_NBRS - 4 +#define PTM_MAX_EDGES 42 //3 * PTM_MAX_NBRS - 6 + + +//------------------------------------ +// number of neighbours +//------------------------------------ +#define PTM_NUM_NBRS_FCC 12 +#define PTM_NUM_NBRS_HCP 12 +#define PTM_NUM_NBRS_BCC 14 +#define PTM_NUM_NBRS_ICO 12 +#define PTM_NUM_NBRS_SC 6 +#define PTM_NUM_NBRS_DCUB 16 +#define PTM_NUM_NBRS_DHEX 16 + +#define PTM_NUM_POINTS_FCC (PTM_NUM_NBRS_FCC + 1) +#define PTM_NUM_POINTS_HCP (PTM_NUM_NBRS_HCP + 1) +#define PTM_NUM_POINTS_BCC (PTM_NUM_NBRS_BCC + 1) +#define PTM_NUM_POINTS_ICO (PTM_NUM_NBRS_ICO + 1) +#define PTM_NUM_POINTS_SC (PTM_NUM_NBRS_SC + 1) +#define PTM_NUM_POINTS_DCUB (PTM_NUM_NBRS_DCUB + 1) +#define PTM_NUM_POINTS_DHEX (PTM_NUM_NBRS_DHEX + 1) + +const int ptm_num_nbrs[8] = {0, PTM_NUM_NBRS_FCC, PTM_NUM_NBRS_HCP, PTM_NUM_NBRS_BCC, PTM_NUM_NBRS_ICO, PTM_NUM_NBRS_SC, PTM_NUM_NBRS_DCUB, PTM_NUM_NBRS_DHEX}; + +//------------------------------------ +// template structures +//------------------------------------ + +//these point sets have barycentre {0, 0, 0} and are scaled such that the mean neighbour distance is 1 + +const double ptm_template_fcc[PTM_NUM_POINTS_FCC][3] = { { 0. , 0. , 0. }, + { 0. , 0.707106781187, 0.707106781187 }, + { 0. , -0.707106781187, -0.707106781187 }, + { 0. , 0.707106781187, -0.707106781187 }, + { 0. , -0.707106781187, 0.707106781187 }, + { 0.707106781187, 0. , 0.707106781187 }, + { -0.707106781187, 0. , -0.707106781187 }, + { 0.707106781187, 0. , -0.707106781187 }, + { -0.707106781187, 0. , 0.707106781187 }, + { 0.707106781187, 0.707106781187, 0. }, + { -0.707106781187, -0.707106781187, 0. }, + { 0.707106781187, -0.707106781187, 0. }, + { -0.707106781187, 0.707106781187, 0. } }; + +const double ptm_template_hcp[PTM_NUM_POINTS_HCP][3] = { { 0. , 0. , 0. }, + { 0.707106781186, 0. , 0.707106781186 }, + { -0.235702260395, -0.942809041583, -0.235702260395 }, + { 0.707106781186, 0.707106781186, 0. }, + { -0.235702260395, -0.235702260395, -0.942809041583 }, + { 0. , 0.707106781186, 0.707106781186 }, + { -0.942809041583, -0.235702260395, -0.235702260395 }, + { -0.707106781186, 0.707106781186, 0. }, + { 0. , 0.707106781186, -0.707106781186 }, + { 0.707106781186, 0. , -0.707106781186 }, + { 0.707106781186, -0.707106781186, 0. }, + { -0.707106781186, 0. , 0.707106781186 }, + { 0. , -0.707106781186, 0.707106781186 } }; + +const double ptm_template_bcc[PTM_NUM_POINTS_BCC][3] = { { 0. , 0. , 0. }, + { -0.541451884327, -0.541451884327, -0.541451884327 }, + { 0.541451884327, 0.541451884327, 0.541451884327 }, + { 0.541451884327, -0.541451884327, -0.541451884327 }, + { -0.541451884327, 0.541451884327, 0.541451884327 }, + { -0.541451884327, 0.541451884327, -0.541451884327 }, + { 0.541451884327, -0.541451884327, 0.541451884327 }, + { -0.541451884327, -0.541451884327, 0.541451884327 }, + { 0.541451884327, 0.541451884327, -0.541451884327 }, + { 0. , 0. , -1.082903768655 }, + { 0. , 0. , 1.082903768655 }, + { 0. , -1.082903768655, 0. }, + { 0. , 1.082903768655, 0. }, + { -1.082903768655, 0. , 0. }, + { 1.082903768655, 0. , 0. } }; + +const double ptm_template_ico[PTM_NUM_POINTS_ICO][3] = { { 0. , 0. , 0. }, + { 0. , 0.525731112119, 0.850650808352 }, + { 0. , -0.525731112119, -0.850650808352 }, + { 0. , 0.525731112119, -0.850650808352 }, + { 0. , -0.525731112119, 0.850650808352 }, + { -0.525731112119, -0.850650808352, 0. }, + { 0.525731112119, 0.850650808352, 0. }, + { 0.525731112119, -0.850650808352, 0. }, + { -0.525731112119, 0.850650808352, 0. }, + { -0.850650808352, 0. , -0.525731112119 }, + { 0.850650808352, 0. , 0.525731112119 }, + { 0.850650808352, 0. , -0.525731112119 }, + { -0.850650808352, 0. , 0.525731112119 } }; + +const double ptm_template_sc[PTM_NUM_POINTS_SC][3] = { { 0. , 0. , 0. }, + { 0. , 0. , -1. }, + { 0. , 0. , 1. }, + { 0. , -1. , 0. }, + { 0. , 1. , 0. }, + { -1. , 0. , 0. }, + { 1. , 0. , 0. } }; + +const double ptm_template_dcub[PTM_NUM_POINTS_DCUB][3] = { { 0. , 0. , 0. }, + { -0.391491627053, 0.391491627053, 0.391491627053 }, + { -0.391491627053, -0.391491627053, -0.391491627053 }, + { 0.391491627053, -0.391491627053, 0.391491627053 }, + { 0.391491627053, 0.391491627053, -0.391491627053 }, + { -0.782983254107, 0. , 0.782983254107 }, + { -0.782983254107, 0.782983254107, 0. }, + { 0. , 0.782983254107, 0.782983254107 }, + { -0.782983254107, -0.782983254107, 0. }, + { -0.782983254107, 0. , -0.782983254107 }, + { 0. , -0.782983254107, -0.782983254107 }, + { 0. , -0.782983254107, 0.782983254107 }, + { 0.782983254107, -0.782983254107, 0. }, + { 0.782983254107, 0. , 0.782983254107 }, + { 0. , 0.782983254107, -0.782983254107 }, + { 0.782983254107, 0. , -0.782983254107 }, + { 0.782983254107, 0.782983254107, 0. } }; + +const double ptm_template_dhex[PTM_NUM_POINTS_DHEX][3] = { { 0. , 0. , 0. }, + { -0.391491627053, -0.391491627053, -0.391491627053 }, + { 0.391491627053, -0.391491627053, 0.391491627053 }, + { -0.391491627053, 0.391491627053, 0.391491627053 }, + { 0.391491627053, 0.391491627053, -0.391491627053 }, + { -0.260994418036, -1.043977672142, -0.260994418036 }, + { -1.043977672142, -0.260994418036, -0.260994418036 }, + { -0.260994418036, -0.260994418036, -1.043977672142 }, + { 0.782983254107, 0. , 0.782983254107 }, + { 0.782983254107, -0.782983254107, 0. }, + { 0. , -0.782983254107, 0.782983254107 }, + { 0. , 0.782983254107, 0.782983254107 }, + { -0.782983254107, 0.782983254107, 0. }, + { -0.782983254107, 0. , 0.782983254107 }, + { 0.782983254107, 0.782983254107, 0. }, + { 0. , 0.782983254107, -0.782983254107 }, + { 0.782983254107, 0. , -0.782983254107 } }; +#endif + diff --git a/src/PTM/ptm_convex_hull_incremental.cpp b/src/PTM/ptm_convex_hull_incremental.cpp new file mode 100644 index 0000000000..c996b17b58 --- /dev/null +++ b/src/PTM/ptm_convex_hull_incremental.cpp @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include +#include "ptm_convex_hull_incremental.h" +#include "ptm_constants.h" + + +#define VISIBLE 1 +#define INVISIBLE 2 +#define BOTH 3 +#define TOLERANCE 1E-8 + +static double norm_squared(double* p) +{ + double x = p[0]; + double y = p[1]; + double z = p[2]; + + return x*x + y*y + z*z; +} + +static double dot_product(const double* a, const double* b) +{ + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; +} + +static void cross_product(double* a, double* b, double* c) +{ + c[0] = a[1] * b[2] - a[2] * b[1]; + c[1] = a[2] * b[0] - a[0] * b[2]; + c[2] = a[0] * b[1] - a[1] * b[0]; +} + +static void calculate_plane_normal(const double (*points)[3], int a, int b, int c, double* plane_normal) +{ + double u[3] = { points[b][0] - points[a][0], + points[b][1] - points[a][1], + points[b][2] - points[a][2] }; + + double v[3] = { points[c][0] - points[a][0], + points[c][1] - points[a][1], + points[c][2] - points[a][2] }; + + cross_product(u, v, plane_normal); + double norm = sqrt(norm_squared(plane_normal)); + plane_normal[0] /= norm; + plane_normal[1] /= norm; + plane_normal[2] /= norm; +} + +static double point_plane_distance(const double* w, const double* plane_point, const double* plane_cross) +{ + return plane_cross[0] * (plane_point[0] - w[0]) + + plane_cross[1] * (plane_point[1] - w[1]) + + plane_cross[2] * (plane_point[2] - w[2]); +} + +static bool calc_max_extent(int num_points, const double (*points)[3], int* min_index, int* max_index) +{ + for (int j=0;j<3;j++) + { + double dmin = DBL_MAX, dmax = -DBL_MAX; + int imin = 0, imax = 0; + + for (int i = 0;i dmax) + { + dmax = d; + imax = i; + } + } + + if (imin == imax) + return false; //degenerate point set + + min_index[j] = imin; + max_index[j] = imax; + } + + return true; +} + +static bool find_third_point(int num_points, const double (*points)[3], int a, int b, int* p_c) +{ + const double* x1 = points[a]; + const double* x2 = points[b]; + + double x2x1[3] = {x2[0] - x1[0], x2[1] - x1[1], x2[2] - x1[2]}; + double ns_x2x1 = norm_squared(x2x1); + + int bi = -1; + double max_dist = 0.0; + for (int i = 0;i max_dist) + { + max_dist = dist; + bi = i; + } + } + + *p_c = bi; + return max_dist > TOLERANCE; +} + +static bool find_fourth_point(int num_points, const double (*points)[3], int a, int b, int c, int* p_d) +{ + double plane_normal[3]; + calculate_plane_normal(points, a, b, c, plane_normal); + + + int bi = -1; + double max_dist = 0.0; + for (int i = 0;i max_dist) + { + max_dist = dist; + bi = i; + } + } + + *p_d = bi; + return max_dist > TOLERANCE; +} + +static int initial_simplex(int num_points, const double (*points)[3], int* initial_vertices) +{ + int min_index[3] = {0}; + int max_index[3] = {0}; + if (!calc_max_extent(num_points, points, min_index, max_index)) + return -1; + + int bi = -1; + double max_dist = 0.0; + for (int i = 0;i<3;i++) + { + int a = min_index[i], b = max_index[i]; + double delta[3] = { points[a][0] - points[b][0], + points[a][1] - points[b][1], + points[a][2] - points[b][2] }; + double dist = norm_squared(delta); + if (dist > max_dist) + { + bi = i; + max_dist = dist; + } + } + + //first two points are (a, b) + int a = min_index[bi], b = max_index[bi], c = -1, d = -1; + + if (!find_third_point(num_points, points, a, b, &c)) + return -2; + + if (!find_fourth_point(num_points, points, a, b, c, &d)) + return -3; + + initial_vertices[0] = a; + initial_vertices[1] = b; + initial_vertices[2] = c; + initial_vertices[3] = d; + return 0; +} + +static bool visible(const double* w, const double* plane_point, const double* plane_normal) +{ + return point_plane_distance(w, plane_point, plane_normal) > 0; +} + +void add_facet(const double (*points)[3], int a, int b, int c, int8_t* facet, double* plane_normal, double* barycentre) +{ + calculate_plane_normal(points, a, b, c, plane_normal); + if (visible(barycentre, points[a], plane_normal)) + { + plane_normal[0] = -plane_normal[0]; + plane_normal[1] = -plane_normal[1]; + plane_normal[2] = -plane_normal[2]; + + facet[0] = b; + facet[1] = a; + facet[2] = c; + } + else + { + facet[0] = a; + facet[1] = b; + facet[2] = c; + } +} + +static int initialize_convex_hull(int num_points, const double (*points)[3], int8_t facets[][3], double plane_normal[][3], bool* processed, int* initial_vertices, double* barycentre) +{ + memset(processed, 0, PTM_MAX_POINTS * sizeof(bool)); + memset(barycentre, 0, 3 * sizeof(double)); + int ret = initial_simplex(num_points, points, initial_vertices); + if (ret != 0) + return ret; + + for (int i = 0;i<4;i++) + { + int a = initial_vertices[i]; + processed[a] = true; + + barycentre[0] += points[a][0]; + barycentre[1] += points[a][1]; + barycentre[2] += points[a][2]; + } + barycentre[0] /= 4; + barycentre[1] /= 4; + barycentre[2] /= 4; + + add_facet(points, initial_vertices[0], initial_vertices[1], initial_vertices[2], facets[0], plane_normal[0], barycentre); + add_facet(points, initial_vertices[0], initial_vertices[1], initial_vertices[3], facets[1], plane_normal[1], barycentre); + add_facet(points, initial_vertices[0], initial_vertices[2], initial_vertices[3], facets[2], plane_normal[2], barycentre); + add_facet(points, initial_vertices[1], initial_vertices[2], initial_vertices[3], facets[3], plane_normal[3], barycentre); + return 0; +} + +int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, int8_t simplex[][3]) +{ + assert( num_points == PTM_NUM_POINTS_FCC + || num_points == PTM_NUM_POINTS_HCP + || num_points == PTM_NUM_POINTS_BCC + || num_points == PTM_NUM_POINTS_ICO + || num_points == PTM_NUM_POINTS_SC + || num_points == PTM_NUM_POINTS_DCUB + || num_points == PTM_NUM_POINTS_DHEX); + + int ret = 0; + int num_prev = ch->num_prev; + ch->num_prev = num_points; + if (!ch->ok || 0) + { + ret = initialize_convex_hull(num_points, points, ch->facets, ch->plane_normal, ch->processed, ch->initial_vertices, ch->barycentre); + if (ret != 0) + return ret; + + ch->num_facets = 4; + num_prev = 0; + } + + for (int i = num_prev;iprocessed[i]) + continue; + ch->processed[i] = true; + + int num_to_add = 0; + int8_t to_add[PTM_MAX_FACETS][3]; + int8_t edge_visible[PTM_MAX_POINTS][PTM_MAX_POINTS]; + memset(edge_visible, 0, sizeof(int8_t) * PTM_MAX_POINTS * PTM_MAX_POINTS); + for (int j = 0;jnum_facets;j++) + { + int a = ch->facets[j][0]; + int b = ch->facets[j][1]; + int c = ch->facets[j][2]; + + int u = 0, v = 0, w = 0; + + double distance = point_plane_distance(points[i], points[a], ch->plane_normal[j]); + bool vis = distance > TOLERANCE; + if (vis) + { + u = edge_visible[a][b] |= VISIBLE; + edge_visible[b][a] |= VISIBLE; + + v = edge_visible[b][c] |= VISIBLE; + edge_visible[c][b] |= VISIBLE; + + w = edge_visible[c][a] |= VISIBLE; + edge_visible[a][c] |= VISIBLE; + + memcpy(ch->facets[j], ch->facets[ch->num_facets-1], 3 * sizeof(int8_t)); + memcpy(ch->plane_normal[j], ch->plane_normal[ch->num_facets-1], 3 * sizeof(double)); + ch->num_facets--; + j--; + } + else + { + u = edge_visible[a][b] |= INVISIBLE; + edge_visible[b][a] |= INVISIBLE; + + v = edge_visible[b][c] |= INVISIBLE; + edge_visible[c][b] |= INVISIBLE; + + w = edge_visible[c][a] |= INVISIBLE; + edge_visible[a][c] |= INVISIBLE; + } + + if (u == BOTH) + { + to_add[num_to_add][0] = i; + to_add[num_to_add][1] = a; + to_add[num_to_add][2] = b; + num_to_add++; + } + + if (v == BOTH) + { + to_add[num_to_add][0] = i; + to_add[num_to_add][1] = b; + to_add[num_to_add][2] = c; + num_to_add++; + } + + if (w == BOTH) + { + to_add[num_to_add][0] = i; + to_add[num_to_add][1] = c; + to_add[num_to_add][2] = a; + num_to_add++; + } + } + + for (int j = 0;jnum_facets >= PTM_MAX_FACETS) + return -4; + + add_facet(points, to_add[j][0], to_add[j][1], to_add[j][2], ch->facets[ch->num_facets], ch->plane_normal[ch->num_facets], ch->barycentre); ch->num_facets++; + } + } + + for (int i=0;inum_facets;i++) + { + int a = ch->facets[i][0]; + int b = ch->facets[i][1]; + int c = ch->facets[i][2]; + if (a == 0 || b == 0 || c == 0) + return 1; //central atom contained in convex hull + + simplex[i][0] = a - 1; + simplex[i][1] = b - 1; + simplex[i][2] = c - 1; + } + + return ret; +} + diff --git a/src/PTM/ptm_convex_hull_incremental.h b/src/PTM/ptm_convex_hull_incremental.h new file mode 100644 index 0000000000..563a0c436a --- /dev/null +++ b/src/PTM/ptm_convex_hull_incremental.h @@ -0,0 +1,27 @@ +#ifndef PTM_CONVEX_HULL_INCREMENTAL_H +#define PTM_CONVEX_HULL_INCREMENTAL_H + + +#include +#include +#include "ptm_constants.h" + + +typedef struct +{ + int8_t facets[PTM_MAX_FACETS][3]; + double plane_normal[PTM_MAX_FACETS][3]; + bool processed[PTM_MAX_POINTS]; + int initial_vertices[4]; + double barycentre[3]; + int num_facets; + int num_prev; + bool ok; + +} convexhull_t; + +void add_facet(const double (*points)[3], int a, int b, int c, int8_t* facet, double* plane_normal, double* barycentre); +int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, int8_t simplex[][3]); + +#endif + diff --git a/src/PTM/ptm_deformation_gradient.cpp b/src/PTM/ptm_deformation_gradient.cpp new file mode 100644 index 0000000000..d566d5ca11 --- /dev/null +++ b/src/PTM/ptm_deformation_gradient.cpp @@ -0,0 +1,37 @@ +#include "ptm_deformation_gradient.h" + + +void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res) +{ + for (int i = 0;i<3;i++) + { + for (int j = 0;j<3;j++) + { + double acc = 0.0; + for (int k = 0;k +#include "ptm_constants.h" + +void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res); + +//sc +#define k_sc 0.5 +const double penrose_sc[PTM_NUM_POINTS_SC][3] = { + {0, 0, 0}, + {0, 0, -k_sc}, + {0, 0, k_sc}, + {0, -k_sc, 0}, + {0, k_sc, 0}, + {-k_sc, 0, 0}, + {k_sc, 0, 0}, + }; + +//fcc +#define k_fcc 0.17677669529663678216 +const double penrose_fcc[PTM_NUM_POINTS_FCC][3] = { + {0, 0, 0}, + {0, k_fcc, k_fcc}, + {0, -k_fcc, -k_fcc}, + {0, k_fcc, -k_fcc}, + {0, -k_fcc, k_fcc}, + {k_fcc, 0, k_fcc}, + {-k_fcc, 0, -k_fcc}, + {k_fcc, 0, -k_fcc}, + {-k_fcc, 0, k_fcc}, + {k_fcc, k_fcc, -0}, + {-k_fcc, -k_fcc, 0}, + {k_fcc, -k_fcc, 0}, + {-k_fcc, k_fcc, -0}, + }; + +//hcp +#define k_hcp 0.17677669529663678216 +const double penrose_hcp[PTM_NUM_POINTS_HCP][3] = { + {0, 0, 0}, + {k_hcp, 0, k_hcp}, + {-k_hcp/3, -4*k_hcp/3, -k_hcp/3}, + {k_hcp, k_hcp, 0}, + {-k_hcp/3, -k_hcp/3, -4*k_hcp/3}, + {0, k_hcp, k_hcp}, + {-4*k_hcp/3, -k_hcp/3, -k_hcp/3}, + {-k_hcp, k_hcp, -0}, + {0, k_hcp, -k_hcp}, + {k_hcp, 0, -k_hcp}, + {k_hcp, -k_hcp, 0}, + {-k_hcp, 0, k_hcp}, + {0, -k_hcp, k_hcp}, + }; + +//ico +#define k_ico 0.13143277802974323576 +#define phi 1.61803398874989490253 +//((1.0 + sqrt(5)) / 2) +const double penrose_ico[PTM_NUM_POINTS_ICO][3] = { + {0, 0, 0}, + {0, k_ico, phi*k_ico}, + {0, -k_ico, -phi*k_ico}, + {0, k_ico, -phi*k_ico}, + {0, -k_ico, phi*k_ico}, + {-k_ico, -phi*k_ico, -0}, + {k_ico, phi*k_ico, 0}, + {k_ico, -phi*k_ico, 0}, + {-k_ico, phi*k_ico, -0}, + {-phi*k_ico, 0, -k_ico}, + {phi*k_ico, 0, k_ico}, + {phi*k_ico, 0, -k_ico}, + {-phi*k_ico, 0, k_ico}, + }; + +//bcc +#define k_bcc 0.11543038598460284017 +const double penrose_bcc[PTM_NUM_POINTS_BCC][3] = { + {0, 0, 0}, + {-k_bcc, -k_bcc, -k_bcc}, + {k_bcc, k_bcc, k_bcc}, + {k_bcc, -k_bcc, -k_bcc}, + {-k_bcc, k_bcc, k_bcc}, + {-k_bcc, k_bcc, -k_bcc}, + {k_bcc, -k_bcc, k_bcc}, + {-k_bcc, -k_bcc, k_bcc}, + {k_bcc, k_bcc, -k_bcc}, + {0, 0, -2*k_bcc}, + {0, 0, 2*k_bcc}, + {0, -2*k_bcc, 0}, + {0, 2*k_bcc, 0}, + {-2*k_bcc, 0, 0}, + {2*k_bcc, 0, -0}, + }; + +//dcub +#define kdcub 0.07095369570691034689 +const double penrose_dcub[PTM_NUM_POINTS_DCUB][3] = { + { 0, 0, 0 }, + { -kdcub, kdcub, kdcub }, + { -kdcub, -kdcub, -kdcub }, + { kdcub, -kdcub, kdcub }, + { kdcub, kdcub, -kdcub }, + { -2 * kdcub, 0, 2 * kdcub }, + { -2 * kdcub, 2 * kdcub, 0 }, + { 0, 2 * kdcub, 2 * kdcub }, + { -2 * kdcub, -2 * kdcub, 0 }, + { -2 * kdcub, 0, -2 * kdcub }, + { 0, -2 * kdcub, -2 * kdcub }, + { 0, -2 * kdcub, 2 * kdcub }, + { 2 * kdcub, -2 * kdcub, 0 }, + { 2 * kdcub, 0, 2 * kdcub }, + { 0, 2 * kdcub, -2 * kdcub }, + { 2 * kdcub, 0, -2 * kdcub }, + { 2 * kdcub, 2 * kdcub, 0 }, + }; + + +#define kdhex 0.04730246380471011397 +const double penrose_dhex[PTM_NUM_POINTS_DHEX][3] = { + { 0, 0, 0 }, + { -kdcub, -kdcub, -kdcub }, + { kdcub, -kdcub, kdcub }, + { -kdcub, kdcub, kdcub }, + { kdcub, kdcub, -kdcub }, + { -kdhex, -4 * kdhex, -kdhex }, + { -4 * kdhex, -kdhex, -kdhex }, + { -kdhex, -kdhex, -4 * kdhex }, + { 2 * kdcub, 0, 2 * kdcub }, + { 2 * kdcub, -2 * kdcub, 0 }, + { 0, -2 * kdcub, 2 * kdcub }, + { 0, 2 * kdcub, 2 * kdcub }, + { -2 * kdcub, 2 * kdcub, 0 }, + { -2 * kdcub, 0, 2 * kdcub }, + { 2 * kdcub, 2 * kdcub, 0 }, + { 0, 2 * kdcub, -2 * kdcub }, + { 2 * kdcub, 0, -2 * kdcub }, + }; +#endif + + diff --git a/src/PTM/ptm_functions.h b/src/PTM/ptm_functions.h new file mode 100644 index 0000000000..cd67d4940d --- /dev/null +++ b/src/PTM/ptm_functions.h @@ -0,0 +1,27 @@ +#ifndef PTM_FUNCTIONS_H +#define PTM_FUNCTIONS_H + +#include +#include +#include "ptm_initialize_data.h" +#include "ptm_constants.h" + + +//------------------------------------ +// function declarations +//------------------------------------ +#ifdef __cplusplus +extern "C" { +#endif + + +int ptm_index( ptm_local_handle_t local_handle, int32_t flags, int num_points, double (*atomic_positions)[3], int32_t* atomic_numbers, bool topological_ordering, //inputs + int32_t* p_type, int32_t* p_alloy_type, double* p_scale, double* p_rmsd, double* q, double* F, double* F_res, double* U, double* P, int8_t* mapping, double* p_interatomic_distance, double* p_lattice_constant); //outputs + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/PTM/ptm_fundamental_mappings.h b/src/PTM/ptm_fundamental_mappings.h new file mode 100644 index 0000000000..3dd7c39cbb --- /dev/null +++ b/src/PTM/ptm_fundamental_mappings.h @@ -0,0 +1,180 @@ +#ifndef PTM_FUNDAMENTAL_MAPPINGS_H +#define PTM_FUNDAMENTAL_MAPPINGS_H + +#include + +#define NUM_CUBIC_MAPPINGS 24 +#define NUM_ICO_MAPPINGS 60 +#define NUM_HEX_MAPPINGS 6 +#define NUM_DCUB_MAPPINGS 12 +#define NUM_DHEX_MAPPINGS 3 + +const int8_t mapping_sc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6}, + {0, 2, 1, 4, 3, 5, 6}, + {0, 2, 1, 3, 4, 6, 5}, + {0, 1, 2, 4, 3, 6, 5}, + {0, 3, 4, 5, 6, 1, 2}, + {0, 5, 6, 2, 1, 4, 3}, + {0, 6, 5, 1, 2, 4, 3}, + {0, 4, 3, 5, 6, 2, 1}, + {0, 5, 6, 1, 2, 3, 4}, + {0, 4, 3, 6, 5, 1, 2}, + {0, 3, 4, 6, 5, 2, 1}, + {0, 6, 5, 2, 1, 3, 4}, + {0, 3, 4, 2, 1, 5, 6}, + {0, 6, 5, 3, 4, 1, 2}, + {0, 1, 2, 5, 6, 4, 3}, + {0, 4, 3, 1, 2, 5, 6}, + {0, 5, 6, 3, 4, 2, 1}, + {0, 1, 2, 6, 5, 3, 4}, + {0, 2, 1, 5, 6, 3, 4}, + {0, 5, 6, 4, 3, 1, 2}, + {0, 3, 4, 1, 2, 6, 5}, + {0, 2, 1, 6, 5, 4, 3}, + {0, 6, 5, 4, 3, 2, 1}, + {0, 4, 3, 2, 1, 6, 5} }; + +const int8_t mapping_fcc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + {0, 2, 1, 4, 3, 7, 8, 5, 6, 11, 12, 9, 10}, + {0, 3, 4, 1, 2, 6, 5, 8, 7, 12, 11, 10, 9}, + {0, 4, 3, 2, 1, 8, 7, 6, 5, 10, 9, 12, 11}, + {0, 9, 10, 11, 12, 1, 2, 4, 3, 5, 6, 8, 7}, + {0, 7, 8, 6, 5, 11, 12, 10, 9, 2, 1, 4, 3}, + {0, 8, 7, 5, 6, 10, 9, 11, 12, 4, 3, 2, 1}, + {0, 11, 12, 9, 10, 2, 1, 3, 4, 7, 8, 6, 5}, + {0, 5, 6, 8, 7, 9, 10, 12, 11, 1, 2, 3, 4}, + {0, 10, 9, 12, 11, 4, 3, 1, 2, 8, 7, 5, 6}, + {0, 12, 11, 10, 9, 3, 4, 2, 1, 6, 5, 7, 8}, + {0, 6, 5, 7, 8, 12, 11, 9, 10, 3, 4, 1, 2}, + {0, 3, 4, 2, 1, 9, 10, 11, 12, 7, 8, 5, 6}, + {0, 12, 11, 9, 10, 8, 7, 5, 6, 1, 2, 4, 3}, + {0, 5, 6, 7, 8, 4, 3, 2, 1, 11, 12, 10, 9}, + {0, 4, 3, 1, 2, 11, 12, 9, 10, 5, 6, 7, 8}, + {0, 9, 10, 12, 11, 7, 8, 6, 5, 3, 4, 2, 1}, + {0, 8, 7, 6, 5, 1, 2, 3, 4, 12, 11, 9, 10}, + {0, 7, 8, 5, 6, 3, 4, 1, 2, 9, 10, 12, 11}, + {0, 11, 12, 10, 9, 5, 6, 8, 7, 4, 3, 1, 2}, + {0, 1, 2, 4, 3, 12, 11, 10, 9, 8, 7, 6, 5}, + {0, 6, 5, 8, 7, 2, 1, 4, 3, 10, 9, 11, 12}, + {0, 10, 9, 11, 12, 6, 5, 7, 8, 2, 1, 3, 4}, + {0, 2, 1, 3, 4, 10, 9, 12, 11, 6, 5, 8, 7} }; + +const int8_t mapping_bcc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, + {0, 4, 3, 2, 1, 7, 8, 5, 6, 10, 9, 12, 11, 13, 14}, + {0, 6, 5, 7, 8, 2, 1, 3, 4, 10, 9, 11, 12, 14, 13}, + {0, 8, 7, 5, 6, 3, 4, 2, 1, 9, 10, 12, 11, 14, 13}, + {0, 1, 2, 7, 8, 3, 4, 5, 6, 11, 12, 13, 14, 9, 10}, + {0, 4, 3, 7, 8, 5, 6, 2, 1, 13, 14, 10, 9, 12, 11}, + {0, 8, 7, 3, 4, 2, 1, 5, 6, 14, 13, 9, 10, 12, 11}, + {0, 4, 3, 5, 6, 2, 1, 7, 8, 12, 11, 13, 14, 10, 9}, + {0, 1, 2, 5, 6, 7, 8, 3, 4, 13, 14, 9, 10, 11, 12}, + {0, 8, 7, 2, 1, 5, 6, 3, 4, 12, 11, 14, 13, 9, 10}, + {0, 6, 5, 3, 4, 7, 8, 2, 1, 11, 12, 14, 13, 10, 9}, + {0, 6, 5, 2, 1, 3, 4, 7, 8, 14, 13, 10, 9, 11, 12}, + {0, 7, 8, 6, 5, 1, 2, 4, 3, 11, 12, 10, 9, 13, 14}, + {0, 3, 4, 6, 5, 8, 7, 1, 2, 14, 13, 11, 12, 9, 10}, + {0, 5, 6, 1, 2, 8, 7, 4, 3, 9, 10, 13, 14, 12, 11}, + {0, 5, 6, 8, 7, 4, 3, 1, 2, 12, 11, 9, 10, 13, 14}, + {0, 7, 8, 1, 2, 4, 3, 6, 5, 13, 14, 11, 12, 10, 9}, + {0, 3, 4, 8, 7, 1, 2, 6, 5, 9, 10, 14, 13, 11, 12}, + {0, 7, 8, 4, 3, 6, 5, 1, 2, 10, 9, 13, 14, 11, 12}, + {0, 5, 6, 4, 3, 1, 2, 8, 7, 13, 14, 12, 11, 9, 10}, + {0, 3, 4, 1, 2, 6, 5, 8, 7, 11, 12, 9, 10, 14, 13}, + {0, 2, 1, 6, 5, 4, 3, 8, 7, 10, 9, 14, 13, 12, 11}, + {0, 2, 1, 8, 7, 6, 5, 4, 3, 14, 13, 12, 11, 10, 9}, + {0, 2, 1, 4, 3, 8, 7, 6, 5, 12, 11, 10, 9, 14, 13} }; + +const int8_t mapping_ico[NUM_ICO_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + {0, 10, 9, 8, 7, 5, 6, 2, 1, 12, 11, 3, 4}, + {0, 1, 2, 9, 10, 7, 8, 11, 12, 5, 6, 3, 4}, + {0, 4, 3, 8, 7, 2, 1, 11, 12, 9, 10, 6, 5}, + {0, 6, 5, 9, 10, 4, 3, 7, 8, 12, 11, 2, 1}, + {0, 12, 11, 3, 4, 7, 8, 10, 9, 2, 1, 6, 5}, + {0, 4, 3, 6, 5, 9, 10, 2, 1, 8, 7, 11, 12}, + {0, 8, 7, 2, 1, 4, 3, 10, 9, 5, 6, 11, 12}, + {0, 10, 9, 3, 4, 12, 11, 5, 6, 8, 7, 2, 1}, + {0, 12, 11, 6, 5, 2, 1, 7, 8, 3, 4, 10, 9}, + {0, 1, 2, 11, 12, 9, 10, 5, 6, 3, 4, 7, 8}, + {0, 8, 7, 11, 12, 5, 6, 4, 3, 2, 1, 10, 9}, + {0, 6, 5, 2, 1, 12, 11, 4, 3, 9, 10, 7, 8}, + {0, 3, 4, 5, 6, 1, 2, 10, 9, 12, 11, 7, 8}, + {0, 3, 4, 7, 8, 12, 11, 1, 2, 5, 6, 10, 9}, + {0, 6, 5, 7, 8, 9, 10, 12, 11, 2, 1, 4, 3}, + {0, 9, 10, 11, 12, 4, 3, 1, 2, 7, 8, 6, 5}, + {0, 11, 12, 9, 10, 1, 2, 4, 3, 8, 7, 5, 6}, + {0, 8, 7, 5, 6, 10, 9, 11, 12, 4, 3, 2, 1}, + {0, 10, 9, 2, 1, 8, 7, 12, 11, 3, 4, 5, 6}, + {0, 12, 11, 2, 1, 10, 9, 6, 5, 7, 8, 3, 4}, + {0, 9, 10, 6, 5, 7, 8, 4, 3, 11, 12, 1, 2}, + {0, 8, 7, 10, 9, 2, 1, 5, 6, 11, 12, 4, 3}, + {0, 6, 5, 12, 11, 7, 8, 2, 1, 4, 3, 9, 10}, + {0, 11, 12, 8, 7, 4, 3, 5, 6, 1, 2, 9, 10}, + {0, 4, 3, 11, 12, 8, 7, 9, 10, 6, 5, 2, 1}, + {0, 4, 3, 9, 10, 11, 12, 6, 5, 2, 1, 8, 7}, + {0, 12, 11, 10, 9, 3, 4, 2, 1, 6, 5, 7, 8}, + {0, 5, 6, 8, 7, 11, 12, 10, 9, 3, 4, 1, 2}, + {0, 7, 8, 6, 5, 12, 11, 9, 10, 1, 2, 3, 4}, + {0, 10, 9, 12, 11, 2, 1, 3, 4, 5, 6, 8, 7}, + {0, 7, 8, 1, 2, 9, 10, 3, 4, 12, 11, 6, 5}, + {0, 5, 6, 1, 2, 3, 4, 11, 12, 8, 7, 10, 9}, + {0, 7, 8, 12, 11, 3, 4, 6, 5, 9, 10, 1, 2}, + {0, 1, 2, 5, 6, 11, 12, 3, 4, 7, 8, 9, 10}, + {0, 11, 12, 1, 2, 5, 6, 9, 10, 4, 3, 8, 7}, + {0, 5, 6, 3, 4, 10, 9, 1, 2, 11, 12, 8, 7}, + {0, 5, 6, 10, 9, 8, 7, 3, 4, 1, 2, 11, 12}, + {0, 3, 4, 12, 11, 10, 9, 7, 8, 1, 2, 5, 6}, + {0, 9, 10, 7, 8, 1, 2, 6, 5, 4, 3, 11, 12}, + {0, 9, 10, 1, 2, 11, 12, 7, 8, 6, 5, 4, 3}, + {0, 7, 8, 3, 4, 1, 2, 12, 11, 6, 5, 9, 10}, + {0, 11, 12, 5, 6, 8, 7, 1, 2, 9, 10, 4, 3}, + {0, 1, 2, 7, 8, 3, 4, 9, 10, 11, 12, 5, 6}, + {0, 3, 4, 10, 9, 5, 6, 12, 11, 7, 8, 1, 2}, + {0, 2, 1, 4, 3, 8, 7, 6, 5, 12, 11, 10, 9}, + {0, 2, 1, 12, 11, 6, 5, 10, 9, 8, 7, 4, 3}, + {0, 9, 10, 4, 3, 6, 5, 11, 12, 1, 2, 7, 8}, + {0, 11, 12, 4, 3, 9, 10, 8, 7, 5, 6, 1, 2}, + {0, 2, 1, 10, 9, 12, 11, 8, 7, 4, 3, 6, 5}, + {0, 5, 6, 11, 12, 1, 2, 8, 7, 10, 9, 3, 4}, + {0, 10, 9, 5, 6, 3, 4, 8, 7, 2, 1, 12, 11}, + {0, 12, 11, 7, 8, 6, 5, 3, 4, 10, 9, 2, 1}, + {0, 7, 8, 9, 10, 6, 5, 1, 2, 3, 4, 12, 11}, + {0, 2, 1, 8, 7, 10, 9, 4, 3, 6, 5, 12, 11}, + {0, 8, 7, 4, 3, 11, 12, 2, 1, 10, 9, 5, 6}, + {0, 6, 5, 4, 3, 2, 1, 9, 10, 7, 8, 12, 11}, + {0, 2, 1, 6, 5, 4, 3, 12, 11, 10, 9, 8, 7}, + {0, 3, 4, 1, 2, 7, 8, 5, 6, 10, 9, 12, 11}, + {0, 4, 3, 2, 1, 6, 5, 8, 7, 11, 12, 9, 10} }; + +const int8_t mapping_hcp[NUM_HEX_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + {0, 5, 6, 1, 2, 3, 4, 9, 10, 12, 11, 8, 7}, + {0, 3, 4, 5, 6, 1, 2, 12, 11, 7, 8, 10, 9}, + {0, 4, 3, 2, 1, 6, 5, 11, 12, 10, 9, 7, 8}, + {0, 2, 1, 6, 5, 4, 3, 8, 7, 11, 12, 9, 10}, + {0, 6, 5, 4, 3, 2, 1, 10, 9, 8, 7, 12, 11} }; + +const int8_t mapping_dcub[NUM_DCUB_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + {0, 2, 1, 4, 3, 9, 8, 10, 6, 5, 7, 14, 16, 15, 11, 13, 12}, + {0, 4, 3, 2, 1, 15, 16, 14, 12, 13, 11, 10, 8, 9, 7, 5, 6}, + {0, 3, 4, 1, 2, 13, 12, 11, 16, 15, 14, 7, 6, 5, 10, 9, 8}, + {0, 4, 2, 1, 3, 14, 15, 16, 9, 10, 8, 6, 5, 7, 12, 11, 13}, + {0, 4, 1, 3, 2, 16, 14, 15, 7, 6, 5, 13, 11, 12, 9, 8, 10}, + {0, 1, 4, 2, 3, 6, 7, 5, 14, 16, 15, 9, 10, 8, 13, 12, 11}, + {0, 3, 1, 2, 4, 11, 13, 12, 5, 7, 6, 8, 9, 10, 16, 14, 15}, + {0, 3, 2, 4, 1, 12, 11, 13, 10, 8, 9, 15, 14, 16, 5, 6, 7}, + {0, 2, 4, 3, 1, 10, 9, 8, 15, 14, 16, 12, 13, 11, 6, 7, 5}, + {0, 1, 3, 4, 2, 7, 5, 6, 13, 11, 12, 16, 15, 14, 8, 10, 9}, + {0, 2, 3, 1, 4, 8, 10, 9, 11, 12, 13, 5, 7, 6, 15, 16, 14} }; + +const int8_t mapping_dhex[NUM_DHEX_MAPPINGS][PTM_MAX_POINTS] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + {0, 1, 3, 4, 2, 6, 7, 5, 11, 13, 12, 14, 16, 15, 8, 9, 10}, + {0, 1, 4, 2, 3, 7, 5, 6, 14, 15, 16, 8, 10, 9, 11, 13, 12} }; + +#endif + diff --git a/src/PTM/ptm_graph_data.cpp b/src/PTM/ptm_graph_data.cpp new file mode 100644 index 0000000000..a591dbf993 --- /dev/null +++ b/src/PTM/ptm_graph_data.cpp @@ -0,0 +1,2059 @@ +#include "ptm_graph_data.h" + + +int8_t automorphisms[65][17] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 4, 3, 10, 9, 5, 6, 12, 11, 8, 7, 1, 2, -1, -1, -1, -1}, + { 0, 5, 6, 11, 12, 8, 7, 2, 1, 4, 3, 10, 9, -1, -1, -1, -1}, + { 0, 8, 7, 1, 2, 4, 3, 9, 10, 5, 6, 11, 12, -1, -1, -1, -1}, + { 0, 8, 7, 10, 9, 1, 2, 6, 5, 12, 11, 3, 4, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 12, 3, 2, 7, 10, 8, 4, 6, 11, 5, 9, 1, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 4, 11, 8, 1, 9, 12, 10, 3, 5, 7, 2, 6, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 2, 1, 6, 5, 4, 3, 9, 8, 7, 11, 10, 12, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 1, 7, 10, 11, 9, 6, 4, 2, 12, 5, 8, 3, -1, -1, -1, -1}, + { 0, 1, 11, 9, 2, 3, 6, 8, 4, 10, 12, 7, 5, -1, -1, -1, -1}, + { 0, 3, 6, 1, 11, 9, 2, 10, 12, 5, 7, 4, 8, -1, -1, -1, -1}, + { 0, 3, 11, 9, 12, 8, 2, 4, 10, 1, 5, 6, 7, -1, -1, -1, -1}, + { 0, 8, 2, 3, 11, 9, 12, 1, 5, 7, 6, 10, 4, -1, -1, -1, -1}, + { 0, 9, 2, 3, 6, 1, 11, 5, 7, 8, 4, 12, 10, -1, -1, -1, -1}, + { 0, 9, 6, 1, 7, 10, 11, 12, 5, 3, 8, 2, 4, -1, -1, -1, -1}, + { 0, 9, 12, 8, 2, 3, 11, 7, 6, 4, 10, 5, 1, -1, -1, -1, -1}, + { 0, 10, 11, 9, 6, 1, 7, 3, 8, 4, 2, 5, 12, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, + { 0, 3, 2, 8, 6, 5, 12, 11, 7, 4, 9, 1, 10, -1, -1, -1, -1}, + { 0, 3, 11, 10, 6, 9, 7, 4, 2, 12, 1, 8, 5, -1, -1, -1, -1}, + { 0, 3, 12, 9, 6, 8, 11, 7, 4, 2, 10, 5, 1, -1, -1, -1, -1}, + { 0, 5, 12, 3, 2, 8, 6, 4, 9, 10, 1, 7, 11, -1, -1, -1, -1}, + { 0, 8, 6, 5, 12, 3, 2, 10, 1, 11, 7, 9, 4, -1, -1, -1, -1}, + { 0, 8, 11, 3, 12, 9, 6, 2, 10, 1, 5, 4, 7, -1, -1, -1, -1}, + { 0, 9, 6, 8, 11, 3, 12, 1, 5, 7, 4, 10, 2, -1, -1, -1, -1}, + { 0, 9, 7, 3, 11, 10, 6, 12, 1, 5, 8, 2, 4, -1, -1, -1, -1}, + { 0, 10, 6, 9, 7, 3, 11, 5, 8, 4, 2, 1, 12, -1, -1, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 3, 4, 6, 5, 2, 1, 9, 10, 14, 13, 11, 12, 8, 7, -1, -1}, + { 0, 4, 3, 1, 2, 5, 6, 10, 9, 13, 14, 7, 8, 12, 11, -1, -1}, + { 0, 6, 5, 1, 2, 4, 3, 14, 13, 7, 8, 11, 12, 10, 9, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 12, 11, 10, 9, 13, 14, 8, 7, 4, 3, 2, 1, 5, 6, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 9, 10, 13, 14, 11, 12, 8, 7, 1, 2, 5, 6, 3, 4, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 6, 5, 4, 3, 2, 1, 11, 12, 10, 9, 7, 8, 14, 13, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 12, 11, 10, 9, 13, 14, 8, 7, 4, 3, 2, 1, 5, 6, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 9, 10, 13, 14, 11, 12, 8, 7, 1, 2, 5, 6, 3, 4, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 3, 10, 14, 5, 9, 7, 13, 2, 8, 4, 11, 12, 1, 6, -1, -1}, + { 0, 13, 8, 1, 10, 4, 14, 6, 9, 5, 2, 11, 12, 7, 3, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 11, 12, 14, 13, 9, 10, 7, 8, 3, 4, 6, 5, 1, 2, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, + { 0, 13, 14, 11, 12, 5, 6, 10, 9, 1, 2, 7, 8, 4, 3, -1, -1}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 4, 3, 2, 1, 15, 14, 16, 13, 12, 11, 10, 9, 8, 6, 5, 7}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 4, 1, 3, 2, 15, 14, 16, 5, 7, 6, 13, 11, 12, 10, 8, 9}, + { 0, 4, 2, 1, 3, 16, 15, 14, 10, 8, 9, 5, 6, 7, 13, 12, 11}, + { 0, 4, 3, 2, 1, 14, 16, 15, 13, 12, 11, 10, 9, 8, 5, 7, 6}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 3, 4, 1, 2, 12, 13, 11, 16, 14, 15, 7, 5, 6, 9, 10, 8}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + { 0, 4, 1, 3, 2, 16, 15, 14, 6, 5, 7, 13, 11, 12, 10, 8, 9}, + { 0, 4, 2, 1, 3, 14, 16, 15, 10, 8, 9, 6, 7, 5, 13, 12, 11}, + { 0, 4, 3, 2, 1, 15, 14, 16, 13, 12, 11, 10, 9, 8, 6, 5, 7}, +}; + +graph_t graphs_sc[NUM_SC_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,4},{1,3,5},{0,3,4},{0,3,5},{1,2,5},{1,2,4},{0,2,4},{0,2,5}}}, + +}; + +graph_t graphs_ico[NUM_ICO_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,5,9},{1,2,8},{0,5,7},{2,7,8},{2,5,7},{1,4,8},{1,2,10},{5,9,10},{2,5,10},{4,8,11},{7,8,11},{0,7,11},{0,3,9},{0,3,11},{3,4,11},{3,6,9},{3,4,6},{6,9,10},{1,4,6},{1,6,10}}}, + +}; + +graph_t graphs_fcc[NUM_FCC_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{1,3,10},{1,3,9},{4,6,10},{4,6,8}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{3,9,10},{1,9,10},{6,8,10},{4,8,10}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{4,6,10},{4,6,8}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{3,9,10},{1,9,10},{4,6,10},{4,6,8}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{7,9,11},{5,9,11},{1,2,6},{1,2,5},{3,9,10},{1,9,10},{4,6,10},{4,6,8}}}, + +{7, +0, +1, +5, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{7,9,11},{5,9,11},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, + +}; + +graph_t graphs_hcp[NUM_HCP_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{6, +0, +6, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{7, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, + +{9, +0, +8, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{12, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{13, +0, +10, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{5,6,7},{3,5,7},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +{14, +0, +12, +10, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{5,6,7},{3,5,7},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, + +{15, +0, +22, +10, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{5,10,11},{1,5,11},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, + +}; + +graph_t graphs_bcc[NUM_BCC_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{7, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{9, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{12, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{13, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{14, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{15, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{16, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{17, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{18, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{19, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{20, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{21, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{22, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{23, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{24, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{25, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{26, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{27, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{28, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{29, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{30, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{31, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{32, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{33, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{34, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{35, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{36, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{37, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{38, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{39, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{40, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{41, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{42, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{43, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{44, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{45, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{46, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{47, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{48, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{49, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{50, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{51, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{52, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{53, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{54, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{55, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{56, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{57, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{58, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{59, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{60, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{61, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{62, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{63, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{64, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{65, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{66, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{67, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{68, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{69, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{70, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{71, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{72, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{73, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{74, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{75, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{76, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{77, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{78, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{79, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{80, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{81, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{82, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{83, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{84, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{85, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{86, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{87, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{88, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{89, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{90, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{91, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{92, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{93, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{94, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{95, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{96, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{97, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{98, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{99, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{100, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{101, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{102, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{103, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{104, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{105, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{106, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{107, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{108, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{109, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{110, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{111, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{112, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{113, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{114, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{115, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{116, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{117, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{118, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{119, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{120, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{121, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{122, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{123, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{124, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{125, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{126, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{127, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{128, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{129, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{130, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{131, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{132, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{133, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{134, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{135, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{136, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{137, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{138, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{139, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{140, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{141, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{142, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{143, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{144, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{145, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{146, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{147, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{148, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{149, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{150, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{151, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{152, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{153, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{154, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{155, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{156, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{157, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{158, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{159, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{160, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{161, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{162, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{163, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{164, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{165, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{166, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{167, +0, +32, +4, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{168, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{169, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{170, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{171, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{172, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{173, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{174, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{175, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{176, +0, +36, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{177, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{178, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{179, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{180, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{181, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{182, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{183, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{184, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{185, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{186, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{187, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{188, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{189, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{190, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{191, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{192, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{193, +0, +38, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{194, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{195, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{196, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{197, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{198, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{199, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{200, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{201, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{202, +0, +40, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, + +{203, +0, +42, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{204, +0, +44, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{205, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{206, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{207, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{208, +0, +46, +3, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{209, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{210, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{211, +0, +49, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, + +{212, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{213, +0, +51, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{214, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{215, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, + +{216, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +{217, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{1,3,11},{1,3,9},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, + +}; + +graph_t graphs_dcub[NUM_DCUB_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{12,14,15},{11,12,14}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, + +{7, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, + +{9, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{4,10,12},{4,6,12},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{4,7,8},{4,5,8},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{12,14,15},{11,12,14}}}, + +}; + +graph_t graphs_dhex[NUM_DHEX_GRAPHS] = { + +{0, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{7,13,15},{7,8,15}}}, + +{1, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{2, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{3, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{4, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{5, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{6, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{7, +0, +53, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{8, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{9, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{10, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{11, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{12, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{13, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{14, +0, +55, +4, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, + +{15, +0, +59, +2, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{16, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{17, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{18, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{19, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{20, +0, +61, +4, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, + +{21, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{22, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +{23, +0, +0, +1, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, + +}; + diff --git a/src/PTM/ptm_graph_data.h b/src/PTM/ptm_graph_data.h new file mode 100644 index 0000000000..11f46a471f --- /dev/null +++ b/src/PTM/ptm_graph_data.h @@ -0,0 +1,37 @@ +#ifndef PTM_GRAPH_DATA_H +#define PTM_GRAPH_DATA_H + +#include +#include "ptm_constants.h" + + +typedef struct +{ + int id; + uint64_t hash; + int automorphism_index; + int num_automorphisms; + int8_t canonical_labelling[PTM_MAX_POINTS]; + int8_t facets[PTM_MAX_FACETS][3]; +} graph_t; + +#define NUM_SC_GRAPHS 1 +#define NUM_ICO_GRAPHS 1 +#define NUM_FCC_GRAPHS 8 +#define NUM_HCP_GRAPHS 16 +#define NUM_BCC_GRAPHS 218 +#define NUM_DCUB_GRAPHS 12 +#define NUM_DHEX_GRAPHS 24 + +extern int8_t automorphisms[][PTM_MAX_POINTS]; + +extern graph_t graphs_sc[NUM_SC_GRAPHS]; +extern graph_t graphs_fcc[NUM_FCC_GRAPHS]; +extern graph_t graphs_hcp[NUM_HCP_GRAPHS]; +extern graph_t graphs_ico[NUM_ICO_GRAPHS]; +extern graph_t graphs_bcc[NUM_BCC_GRAPHS]; +extern graph_t graphs_dcub[NUM_DCUB_GRAPHS]; +extern graph_t graphs_dhex[NUM_DHEX_GRAPHS]; + +#endif + diff --git a/src/PTM/ptm_graph_tools.cpp b/src/PTM/ptm_graph_tools.cpp new file mode 100644 index 0000000000..89d07fc87a --- /dev/null +++ b/src/PTM/ptm_graph_tools.cpp @@ -0,0 +1,52 @@ +#include +#include +#include "ptm_graph_tools.h" +#include "ptm_constants.h" + + +bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]) +{ + memset(common, -1, sizeof(int8_t) * PTM_MAX_NBRS * PTM_MAX_NBRS); + + for (int i = 0;i +#include "ptm_constants.h" + +bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]); +int graph_degree(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree); + +#endif + diff --git a/src/PTM/ptm_index.cpp b/src/PTM/ptm_index.cpp new file mode 100644 index 0000000000..7b6618848e --- /dev/null +++ b/src/PTM/ptm_index.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ptm_convex_hull_incremental.h" +#include "ptm_graph_data.h" +#include "ptm_deformation_gradient.h" +#include "ptm_alloy_types.h" +#include "ptm_neighbour_ordering.h" +#include "ptm_normalize_vertices.h" +#include "ptm_quat.h" +#include "ptm_polar.h" +#include "ptm_initialize_data.h" +#include "ptm_structure_matcher.h" +#include "ptm_functions.h" +#include "ptm_constants.h" + + +//todo: verify that c == norm(template[1]) +static double calculate_interatomic_distance(int type, double scale) +{ + assert(type >= 1 && type <= 7); + double c[8] = {0, 1, 1, (7. - 3.5 * sqrt(3)), 1, 1, sqrt(3) * 4. / (6 * sqrt(2) + sqrt(3)), sqrt(3) * 4. / (6 * sqrt(2) + sqrt(3))}; + return c[type] / scale; +} + +static double calculate_lattice_constant(int type, double interatomic_distance) +{ + assert(type >= 1 && type <= 7); + double c[8] = {0, 2 / sqrt(2), 2 / sqrt(2), 2. / sqrt(3), 2 / sqrt(2), 1, 4 / sqrt(3), 4 / sqrt(3)}; + return c[type] * interatomic_distance; +} + +static int rotate_into_fundamental_zone(int type, double* q) +{ + if (type == PTM_MATCH_SC) return rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_FCC) return rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_BCC) return rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_ICO) return rotate_quaternion_into_icosahedral_fundamental_zone(q); + if (type == PTM_MATCH_HCP) return rotate_quaternion_into_hcp_fundamental_zone(q); + if (type == PTM_MATCH_DCUB) return rotate_quaternion_into_diamond_cubic_fundamental_zone(q); + if (type == PTM_MATCH_DHEX) return rotate_quaternion_into_diamond_hexagonal_fundamental_zone(q); + return -1; +} + +static void order_points(ptm_local_handle_t local_handle, int num_points, double (*unpermuted_points)[3], int32_t* unpermuted_numbers, bool topological_ordering, + int8_t* ordering, double (*points)[3], int32_t* numbers) +{ + if (topological_ordering) + { + double normalized_points[PTM_MAX_INPUT_POINTS][3]; + normalize_vertices(num_points, unpermuted_points, normalized_points); + int ret = calculate_neighbour_ordering((void*)local_handle, num_points, (const double (*)[3])normalized_points, ordering); + if (ret != 0) + topological_ordering = false; + } + + if (!topological_ordering) + for (int i=0;iref_struct; + if (ref == NULL) + return; + + *p_type = ref->type; + if (p_alloy_type != NULL && unpermuted_numbers != NULL) + *p_alloy_type = find_alloy_type(ref, res->mapping, numbers); + + int bi = rotate_into_fundamental_zone(ref->type, res->q); + int8_t temp[PTM_MAX_POINTS]; + for (int i=0;inum_nbrs+1;i++) + temp[ref->mapping[bi][i]] = res->mapping[i]; + + memcpy(res->mapping, temp, (ref->num_nbrs+1) * sizeof(int8_t)); + + if (F != NULL && F_res != NULL) + { + double scaled_points[PTM_MAX_INPUT_POINTS][3]; + + subtract_barycentre(ref->num_nbrs + 1, points, scaled_points); + for (int i = 0;inum_nbrs + 1;i++) + { + scaled_points[i][0] *= res->scale; + scaled_points[i][1] *= res->scale; + scaled_points[i][2] *= res->scale; + } + calculate_deformation_gradient(ref->num_nbrs + 1, ref->points, res->mapping, scaled_points, ref->penrose, F, F_res); + + if (P != NULL && U != NULL) + polar_decomposition_3x3(F, false, U, P); + } + + if (mapping != NULL) + for (int i=0;inum_nbrs + 1;i++) + mapping[i] = ordering[res->mapping[i]]; + + double interatomic_distance = calculate_interatomic_distance(ref->type, res->scale); + double lattice_constant = calculate_lattice_constant(ref->type, interatomic_distance); + + if (p_interatomic_distance != NULL) + *p_interatomic_distance = interatomic_distance; + + if (p_lattice_constant != NULL) + *p_lattice_constant = lattice_constant; + + *p_rmsd = res->rmsd; + *p_scale = res->scale; + memcpy(q, res->q, 4 * sizeof(double)); +} + + +extern bool ptm_initialized; + +int ptm_index( ptm_local_handle_t local_handle, int32_t flags, + int num_points, double (*unpermuted_points)[3], int32_t* unpermuted_numbers, bool topological_ordering, + int32_t* p_type, int32_t* p_alloy_type, double* p_scale, double* p_rmsd, double* q, double* F, double* F_res, + double* U, double* P, int8_t* mapping, double* p_interatomic_distance, double* p_lattice_constant) +{ + assert(ptm_initialized); + assert(num_points <= PTM_MAX_INPUT_POINTS); + + if (flags & PTM_CHECK_SC) + assert(num_points >= PTM_NUM_POINTS_SC); + + if (flags & PTM_CHECK_BCC) + assert(num_points >= PTM_NUM_POINTS_BCC); + + if (flags & (PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO)) + assert(num_points >= PTM_NUM_POINTS_FCC); + + if (flags & (PTM_CHECK_DCUB | PTM_CHECK_DHEX)) + assert(num_points >= PTM_NUM_POINTS_DCUB); + + int ret = 0; + result_t res; + res.ref_struct = NULL; + res.rmsd = INFINITY; + + int8_t ordering[PTM_MAX_INPUT_POINTS]; + double points[PTM_MAX_POINTS][3]; + int32_t numbers[PTM_MAX_POINTS]; + + int8_t dordering[PTM_MAX_INPUT_POINTS]; + double dpoints[PTM_MAX_POINTS][3]; + int32_t dnumbers[PTM_MAX_POINTS]; + + convexhull_t ch; + double ch_points[PTM_MAX_INPUT_POINTS][3]; + + if (flags & (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC)) + { + int num_lpoints = std::min(std::min(PTM_MAX_POINTS, 20), num_points); + order_points(local_handle, num_lpoints, unpermuted_points, unpermuted_numbers, topological_ordering, ordering, points, numbers); + normalize_vertices(num_lpoints, points, ch_points); + ch.ok = false; + + if (flags & PTM_CHECK_SC) + ret = match_general(&structure_sc, ch_points, points, &ch, &res); + + if (flags & (PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO)) + ret = match_fcc_hcp_ico(ch_points, points, flags, &ch, &res); + + if (flags & PTM_CHECK_BCC) + ret = match_general(&structure_bcc, ch_points, points, &ch, &res); + } + + if (flags & (PTM_CHECK_DCUB | PTM_CHECK_DHEX)) + { + ret = calculate_diamond_neighbour_ordering(num_points, unpermuted_points, unpermuted_numbers, dordering, dpoints, dnumbers); + if (ret == 0) + { + normalize_vertices(PTM_NUM_NBRS_DCUB + 1, dpoints, ch_points); + ch.ok = false; + + ret = match_dcub_dhex(ch_points, dpoints, flags, &ch, &res); + } + } + + if (res.ref_struct != NULL && (res.ref_struct->type == PTM_MATCH_DCUB || res.ref_struct->type == PTM_MATCH_DHEX)) + { + output_data( &res, num_points, unpermuted_numbers, dpoints, dnumbers, dordering, + p_type, p_alloy_type, p_scale, p_rmsd, q, F, F_res, + U, P, mapping, p_interatomic_distance, p_lattice_constant); + } + else + { + output_data( &res, num_points, unpermuted_numbers, points, numbers, ordering, + p_type, p_alloy_type, p_scale, p_rmsd, q, F, F_res, + U, P, mapping, p_interatomic_distance, p_lattice_constant); + } + + return PTM_NO_ERROR; +} + diff --git a/src/PTM/ptm_initialize_data.cpp b/src/PTM/ptm_initialize_data.cpp new file mode 100644 index 0000000000..6157ff862f --- /dev/null +++ b/src/PTM/ptm_initialize_data.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ptm_initialize_data.h" + + +static void make_facets_clockwise(int num_facets, int8_t (*facets)[3], const double (*points)[3]) +{ + double plane_normal[3]; + double origin[3] = {0, 0, 0}; + + for (int i = 0;inum_graphs;i++) + { + int8_t code[2 * PTM_MAX_EDGES]; + int8_t degree[PTM_MAX_NBRS]; + int _max_degree = graph_degree(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree); + assert(_max_degree <= s->max_degree); + + make_facets_clockwise(s->num_facets, s->graphs[i].facets, &s->points[1]); + int ret = canonical_form_coloured(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree, colours, s->graphs[i].canonical_labelling, (int8_t*)&code[0], &s->graphs[i].hash); + if (ret != 0) + return ret; + } + + return PTM_NO_ERROR; +} + +bool ptm_initialized = false; +int ptm_initialize_global() +{ + if (ptm_initialized) + return PTM_NO_ERROR; + + int8_t colours[PTM_MAX_POINTS] = {0}; + int8_t dcolours[PTM_MAX_POINTS] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + int ret = initialize_graphs(&structure_sc, colours); + ret |= initialize_graphs(&structure_fcc, colours); + ret |= initialize_graphs(&structure_hcp, colours); + ret |= initialize_graphs(&structure_ico, colours); + ret |= initialize_graphs(&structure_bcc, colours); + ret |= initialize_graphs(&structure_dcub, dcolours); + ret |= initialize_graphs(&structure_dhex, dcolours); + + if (ret == PTM_NO_ERROR) + ptm_initialized = true; + + return ret; +} + +ptm_local_handle_t ptm_initialize_local() +{ + assert(ptm_initialized); + return (ptm_local_handle_t)voronoi_initialize_local(); +} + +void ptm_uninitialize_local(ptm_local_handle_t ptr) +{ + voronoi_uninitialize_local(ptr); +} + diff --git a/src/PTM/ptm_initialize_data.h b/src/PTM/ptm_initialize_data.h new file mode 100644 index 0000000000..f381dd864b --- /dev/null +++ b/src/PTM/ptm_initialize_data.h @@ -0,0 +1,61 @@ +#ifndef PTM_INITIALIZE_DATA_H +#define PTM_INITIALIZE_DATA_H + + +#include "ptm_graph_data.h" +#include "ptm_graph_tools.h" +#include "ptm_deformation_gradient.h" +#include "ptm_fundamental_mappings.h" +#include "ptm_neighbour_ordering.h" +#include "ptm_canonical_coloured.h" +#include "ptm_convex_hull_incremental.h" + + +typedef struct +{ + int type; + int num_nbrs; + int num_facets; + int max_degree; + int num_graphs; + int num_mappings; + graph_t* graphs; + const double (*points)[3]; + const double (*penrose)[3]; + const int8_t (*mapping)[PTM_MAX_POINTS]; +} refdata_t; + + +//refdata_t structure_sc = { .type = PTM_MATCH_SC, .num_nbrs = 6, .num_facets = 8, .max_degree = 4, .num_graphs = NUM_SC_GRAPHS, .graphs = graphs_sc, .points = ptm_template_sc, .penrose = penrose_sc , .mapping = mapping_sc }; +const refdata_t structure_sc = { PTM_MATCH_SC, 6, 8, 4, NUM_SC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_sc, ptm_template_sc, penrose_sc, mapping_sc }; +const refdata_t structure_fcc = { PTM_MATCH_FCC, 12, 20, 6, NUM_FCC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_fcc, ptm_template_fcc, penrose_fcc, mapping_fcc }; +const refdata_t structure_hcp = { PTM_MATCH_HCP, 12, 20, 6, NUM_HCP_GRAPHS, NUM_HEX_MAPPINGS, graphs_hcp, ptm_template_hcp, penrose_hcp, mapping_hcp }; +const refdata_t structure_ico = { PTM_MATCH_ICO, 12, 20, 6, NUM_ICO_GRAPHS, NUM_ICO_MAPPINGS, graphs_ico, ptm_template_ico, penrose_ico, mapping_ico }; +const refdata_t structure_bcc = { PTM_MATCH_BCC, 14, 24, 8, NUM_BCC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_bcc, ptm_template_bcc, penrose_bcc, mapping_bcc }; +const refdata_t structure_dcub = { PTM_MATCH_DCUB, 16, 28, 8, NUM_DCUB_GRAPHS, NUM_DCUB_MAPPINGS, graphs_dcub, ptm_template_dcub, penrose_dcub, mapping_dcub }; +const refdata_t structure_dhex = { PTM_MATCH_DHEX, 16, 28, 8, NUM_DHEX_GRAPHS, NUM_DHEX_MAPPINGS, graphs_dhex, ptm_template_dhex, penrose_dhex, mapping_dhex }; + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ptm_local_handle* ptm_local_handle_t; +ptm_local_handle_t ptm_initialize_local(); +void ptm_uninitialize_local(ptm_local_handle_t ptr); + +int ptm_initialize_global(); + +//------------------------------------ +// global initialization switch +//------------------------------------ +extern bool ptm_initialized; + + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/src/PTM/ptm_neighbour_ordering.cpp b/src/PTM/ptm_neighbour_ordering.cpp new file mode 100644 index 0000000000..6b5ac9601a --- /dev/null +++ b/src/PTM/ptm_neighbour_ordering.cpp @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#include +#include "ptm_constants.h" +#include "ptm_voronoi_cell.h" +using namespace voro; + + + +typedef struct +{ + double area; + double dist; + int index; +} sorthelper_t; + +static bool sorthelper_compare(sorthelper_t const& a, sorthelper_t const& b) +{ + if (a.area > b.area) + return true; + + if (a.area < b.area) + return false; + + if (a.dist < b.dist) + return true; + + return false; +} + +//todo: change voronoi code to return errors rather than exiting +static int calculate_voronoi_face_areas(int num_points, const double (*_points)[3], double* normsq, double max_norm, voronoicell_neighbor* v, std::vector& nbr_indices, std::vector& face_areas) +{ + const double k = 1000 * max_norm; //todo: reduce this constant + v->init(-k,k,-k,k,-k,k); + + for (int i=1;inplane(x,y,z,normsq[i],i); + } + + v->neighbors(nbr_indices); + v->face_areas(face_areas); + return 0; +} + +int calculate_neighbour_ordering(void* _voronoi_handle, int num_points, const double (*_points)[3], int8_t* ordering) +{ + assert(num_points <= PTM_MAX_INPUT_POINTS); + + voronoicell_neighbor* voronoi_handle = (voronoicell_neighbor*)_voronoi_handle; + + double max_norm = 0; + double points[PTM_MAX_INPUT_POINTS][3]; + double normsq[PTM_MAX_INPUT_POINTS]; + for (int i = 0;i nbr_indices(num_points + 6); + std::vector face_areas(num_points + 6); + int ret = calculate_voronoi_face_areas(num_points, points, normsq, max_norm, voronoi_handle, nbr_indices, face_areas); + if (ret != 0) + return ret; + + double areas[PTM_MAX_INPUT_POINTS]; + memset(areas, 0, num_points * sizeof(double)); + areas[0] = INFINITY; + for (size_t i=0;i 0) + areas[index] = face_areas[i]; + } + + sorthelper_t data[PTM_MAX_INPUT_POINTS]; + for (int i=0;i= 3) + continue; + + ordering[1 + 4 + 3 * p + counts[p]] = q; + counts[p]++; + index++; + num_found++; + if (num_found >= 12) + break; + } + + if (num_found != 12) + return -1; + + for (int i=0;i + + +void subtract_barycentre(int num, double (*points)[3], double (*normalized)[3]) +{ + //calculate barycentre + double sum[3] = {0, 0, 0}; + for (int i=0;i nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Source: started anew. + * + * Change History: + * 2009/04/13 Started source + * 2010/03/28 Modified FastCalcRMSDAndRotation() to handle tiny qsqr + * If trying all rows of the adjoint still gives too small + * qsqr, then just return identity matrix. (DLT) + * 2010/06/30 Fixed prob in assigning A[9] = 0 in InnerProduct() + * invalid mem access + * 2011/02/21 Made CenterCoords use weights + * 2011/05/02 Finally changed CenterCoords declaration in qcprot.h + * Also changed some functions to static + * 2011/07/08 put in fabs() to fix taking sqrt of small neg numbers, fp error + * 2012/07/26 minor changes to comments and main.c, more info (v.1.4) + * + * 2016/05/29 QCP method adapted for polar decomposition of a 3x3 matrix, + * for use in Polyhedral Template Matching. + * + ******************************************************************************/ + +#include +#include +#include +#include "ptm_quat.h" + + +static void matmul_3x3(double* A, double* x, double* b) +{ + b[0] = A[0] * x[0] + A[1] * x[3] + A[2] * x[6]; + b[3] = A[3] * x[0] + A[4] * x[3] + A[5] * x[6]; + b[6] = A[6] * x[0] + A[7] * x[3] + A[8] * x[6]; + + b[1] = A[0] * x[1] + A[1] * x[4] + A[2] * x[7]; + b[4] = A[3] * x[1] + A[4] * x[4] + A[5] * x[7]; + b[7] = A[6] * x[1] + A[7] * x[4] + A[8] * x[7]; + + b[2] = A[0] * x[2] + A[1] * x[5] + A[2] * x[8]; + b[5] = A[3] * x[2] + A[4] * x[5] + A[5] * x[8]; + b[8] = A[6] * x[2] + A[7] * x[5] + A[8] * x[8]; +} + +static double matrix_determinant_3x3(double* A) +{ + return A[0] * (A[4]*A[8] - A[5]*A[7]) + - A[1] * (A[3]*A[8] - A[5]*A[6]) + + A[2] * (A[3]*A[7] - A[4]*A[6]); +} + +static void flip_matrix(double* A) +{ + for (int i=0;i<9;i++) + A[i] = -A[i]; +} + +static bool optimal_quaternion(double* A, bool polar, double E0, double* p_nrmsdsq, double* qopt) +{ + const double evecprec = 1e-6; + const double evalprec = 1e-11; + + double Sxx = A[0], Sxy = A[1], Sxz = A[2], + Syx = A[3], Syy = A[4], Syz = A[5], + Szx = A[6], Szy = A[7], Szz = A[8]; + + double Sxx2 = Sxx * Sxx, Syy2 = Syy * Syy, Szz2 = Szz * Szz, + Sxy2 = Sxy * Sxy, Syz2 = Syz * Syz, Sxz2 = Sxz * Sxz, + Syx2 = Syx * Syx, Szy2 = Szy * Szy, Szx2 = Szx * Szx; + + double fnorm_squared = Sxx2 + Syy2 + Szz2 + Sxy2 + Syz2 + Sxz2 + Syx2 + Szy2 + Szx2; + + double SyzSzymSyySzz2 = 2.0 * (Syz * Szy - Syy * Szz); + double Sxx2Syy2Szz2Syz2Szy2 = Syy2 + Szz2 - Sxx2 + Syz2 + Szy2; + double SxzpSzx = Sxz + Szx; + double SyzpSzy = Syz + Szy; + double SxypSyx = Sxy + Syx; + double SyzmSzy = Syz - Szy; + double SxzmSzx = Sxz - Szx; + double SxymSyx = Sxy - Syx; + double SxxpSyy = Sxx + Syy; + double SxxmSyy = Sxx - Syy; + double Sxy2Sxz2Syx2Szx2 = Sxy2 + Sxz2 - Syx2 - Szx2; + + double C[3]; + C[0] = Sxy2Sxz2Syx2Szx2 * Sxy2Sxz2Syx2Szx2 + + (Sxx2Syy2Szz2Syz2Szy2 + SyzSzymSyySzz2) * (Sxx2Syy2Szz2Syz2Szy2 - SyzSzymSyySzz2) + + (-(SxzpSzx)*(SyzmSzy)+(SxymSyx)*(SxxmSyy-Szz)) * (-(SxzmSzx)*(SyzpSzy)+(SxymSyx)*(SxxmSyy+Szz)) + + (-(SxzpSzx)*(SyzpSzy)-(SxypSyx)*(SxxpSyy-Szz)) * (-(SxzmSzx)*(SyzmSzy)-(SxypSyx)*(SxxpSyy+Szz)) + + (+(SxypSyx)*(SyzpSzy)+(SxzpSzx)*(SxxmSyy+Szz)) * (-(SxymSyx)*(SyzmSzy)+(SxzpSzx)*(SxxpSyy+Szz)) + + (+(SxypSyx)*(SyzmSzy)+(SxzmSzx)*(SxxmSyy-Szz)) * (-(SxymSyx)*(SyzpSzy)+(SxzmSzx)*(SxxpSyy-Szz)); + + C[1] = 8.0 * (Sxx*Syz*Szy + Syy*Szx*Sxz + Szz*Sxy*Syx - Sxx*Syy*Szz - Syz*Szx*Sxy - Szy*Syx*Sxz); + C[2] = -2.0 * fnorm_squared; + + //Newton-Raphson + double mxEigenV = polar ? sqrt(3 * fnorm_squared) : E0; + if (mxEigenV > evalprec) + { + for (int i=0;i<50;i++) + { + double oldg = mxEigenV; + double x2 = mxEigenV*mxEigenV; + double b = (x2 + C[2])*mxEigenV; + double a = b + C[1]; + double delta = ((a * mxEigenV + C[0]) / (2 * x2 * mxEigenV + b + a)); + mxEigenV -= delta; + if (fabs(mxEigenV - oldg) < fabs(evalprec * mxEigenV)) + break; + } + } + else + { + mxEigenV = 0.0; + } + + (*p_nrmsdsq) = std::max(0.0, 2.0 * (E0 - mxEigenV)); + + double a11 = SxxpSyy + Szz - mxEigenV; + double a12 = SyzmSzy; + double a13 = -SxzmSzx; + double a14 = SxymSyx; + + double a21 = SyzmSzy; + double a22 = SxxmSyy - Szz -mxEigenV; + double a23 = SxypSyx; + double a24 = SxzpSzx; + + double a31 = a13; + double a32 = a23; + double a33 = Syy - Sxx - Szz - mxEigenV; + double a34 = SyzpSzy; + + double a41 = a14; + double a42 = a24; + double a43 = a34; + double a44 = Szz - SxxpSyy - mxEigenV; + + double a3344_4334 = a33 * a44 - a43 * a34; + double a3244_4234 = a32 * a44 - a42 * a34; + double a3243_4233 = a32 * a43 - a42 * a33; + double a3143_4133 = a31 * a43 - a41 * a33; + double a3144_4134 = a31 * a44 - a41 * a34; + double a3142_4132 = a31 * a42 - a41 * a32; + double a1324_1423 = a13 * a24 - a14 * a23; + double a1224_1422 = a12 * a24 - a14 * a22; + double a1223_1322 = a12 * a23 - a13 * a22; + double a1124_1421 = a11 * a24 - a14 * a21; + double a1123_1321 = a11 * a23 - a13 * a21; + double a1122_1221 = a11 * a22 - a12 * a21; + + double q[4][4]; + q[0][0] = a12 * a3344_4334 - a13 * a3244_4234 + a14 * a3243_4233; + q[0][1] = -a11 * a3344_4334 + a13 * a3144_4134 - a14 * a3143_4133; + q[0][2] = a11 * a3244_4234 - a12 * a3144_4134 + a14 * a3142_4132; + q[0][3] = -a11 * a3243_4233 + a12 * a3143_4133 - a13 * a3142_4132; + + q[1][0] = a22 * a3344_4334 - a23 * a3244_4234 + a24 * a3243_4233; + q[1][1] = -a21 * a3344_4334 + a23 * a3144_4134 - a24 * a3143_4133; + q[1][2] = a21 * a3244_4234 - a22 * a3144_4134 + a24 * a3142_4132; + q[1][3] = -a21 * a3243_4233 + a22 * a3143_4133 - a23 * a3142_4132; + + q[2][0] = a32 * a1324_1423 - a33 * a1224_1422 + a34 * a1223_1322; + q[2][1] = -a31 * a1324_1423 + a33 * a1124_1421 - a34 * a1123_1321; + q[2][2] = a31 * a1224_1422 - a32 * a1124_1421 + a34 * a1122_1221; + q[2][3] = -a31 * a1223_1322 + a32 * a1123_1321 - a33 * a1122_1221; + + q[3][0] = a42 * a1324_1423 - a43 * a1224_1422 + a44 * a1223_1322; + q[3][1] = -a41 * a1324_1423 + a43 * a1124_1421 - a44 * a1123_1321; + q[3][2] = a41 * a1224_1422 - a42 * a1124_1421 + a44 * a1122_1221; + q[3][3] = -a41 * a1223_1322 + a42 * a1123_1321 - a43 * a1122_1221; + + double qsqr[4]; + for (int i=0;i<4;i++) + qsqr[i] = q[i][0]*q[i][0] + q[i][1]*q[i][1] + q[i][2]*q[i][2] + q[i][3]*q[i][3]; + + int bi = 0; + double max = 0; + for (int i=0;i<4;i++) + { + if (qsqr[i] > max) + { + bi = i; + max = qsqr[i]; + } + } + + bool too_small = false; + if (qsqr[bi] < evecprec) + { + //if qsqr is still too small, return the identity rotation. + q[bi][0] = 1; + q[bi][1] = 0; + q[bi][2] = 0; + q[bi][3] = 0; + too_small = true; + } + else + { + double normq = sqrt(qsqr[bi]); + q[bi][0] /= normq; + q[bi][1] /= normq; + q[bi][2] /= normq; + q[bi][3] /= normq; + } + + memcpy(qopt, q[bi], 4 * sizeof(double)); + return !too_small; +} + +int polar_decomposition_3x3(double* _A, bool right_sided, double* U, double* P) +{ + double A[9]; + memcpy(A, _A, 9 * sizeof(double)); + + double det = matrix_determinant_3x3(A); + if (det < 0) + flip_matrix(A); + + double q[4]; + double nrmsdsq = 0; + optimal_quaternion(A, true, -1, &nrmsdsq, q); + q[0] = -q[0]; + quaternion_to_rotation_matrix(q, U); + + if (det < 0) + flip_matrix(U); + + double UT[9] = {U[0], U[3], U[6], U[1], U[4], U[7], U[2], U[5], U[8]}; + + if (right_sided) + matmul_3x3(UT, _A, P); + else + matmul_3x3(_A, UT, P); + + return 0; +} + +void InnerProduct(double *A, int num, const double (*coords1)[3], double (*coords2)[3], int8_t* permutation) +{ + A[0] = A[1] = A[2] = A[3] = A[4] = A[5] = A[6] = A[7] = A[8] = 0.0; + + for (int i = 0; i < num; ++i) + { + double x1 = coords1[i][0]; + double y1 = coords1[i][1]; + double z1 = coords1[i][2]; + + double x2 = coords2[permutation[i]][0]; + double y2 = coords2[permutation[i]][1]; + double z2 = coords2[permutation[i]][2]; + + A[0] += x1 * x2; + A[1] += x1 * y2; + A[2] += x1 * z2; + + A[3] += y1 * x2; + A[4] += y1 * y2; + A[5] += y1 * z2; + + A[6] += z1 * x2; + A[7] += z1 * y2; + A[8] += z1 * z2; + } +} + +int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, double* U) +{ + optimal_quaternion(A, false, E0, p_nrmsdsq, q); + quaternion_to_rotation_matrix(q, U); + return 0; +} + diff --git a/src/PTM/ptm_polar.h b/src/PTM/ptm_polar.h new file mode 100644 index 0000000000..d5aa3d9540 --- /dev/null +++ b/src/PTM/ptm_polar.h @@ -0,0 +1,12 @@ +#ifndef PTM_POLAR_H +#define PTM_POLAR_H + +#include +#include + +int polar_decomposition_3x3(double* _A, bool right_sided, double* U, double* P); +void InnerProduct(double *A, int num, const double (*coords1)[3], double (*coords2)[3], int8_t* permutation); +int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, double* U); + +#endif + diff --git a/src/PTM/ptm_quat.cpp b/src/PTM/ptm_quat.cpp new file mode 100644 index 0000000000..f55aff3d2b --- /dev/null +++ b/src/PTM/ptm_quat.cpp @@ -0,0 +1,396 @@ +#include +#include +#include + + +#define SIGN(x) (x >= 0 ? 1 : -1) +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) +#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) + + +#define SQRT_2 1.4142135623730951454746218587388284504414 +#define HALF_SQRT_2 0.7071067811865474617150084668537601828575 + +#define PHI 1.6180339887498949025257388711906969547272 +#define HALF_PHI 0.8090169943749474512628694355953484773636 + +#define INV_PHI 0.6180339887498947915034364086750429123640 +#define HALF_INV_PHI 0.3090169943749473957517182043375214561820 + +#define SQRT_5_ 2.23606797749978969640917366873127623544061835961152572427089 +#define SQRT_2_3 0.8164965809277260344600790631375275552273 +#define SQRT_1_6 0.4082482904638630172300395315687637776136 + + +double generator_cubic[24][4] = { {1, 0, 0, 0 }, + {0, 1, 0, 0 }, + {0, 0, 1, 0 }, + {0, 0, 0, 1 }, + {0.5, 0.5, 0.5, 0.5 }, + {0.5, 0.5, -0.5, 0.5 }, + {0.5, -0.5, 0.5, 0.5 }, + {0.5, -0.5, -0.5, 0.5 }, + {-0.5, 0.5, 0.5, 0.5 }, + {-0.5, 0.5, -0.5, 0.5 }, + {-0.5, -0.5, 0.5, 0.5 }, + {-0.5, -0.5, -0.5, 0.5 }, + {HALF_SQRT_2, HALF_SQRT_2, 0, 0 }, + {HALF_SQRT_2, 0, HALF_SQRT_2, 0 }, + {HALF_SQRT_2, 0, 0, HALF_SQRT_2 }, + {-HALF_SQRT_2, HALF_SQRT_2, 0, 0 }, + {-HALF_SQRT_2, 0, HALF_SQRT_2, 0 }, + {-HALF_SQRT_2, 0, 0, HALF_SQRT_2 }, + {0, HALF_SQRT_2, HALF_SQRT_2, 0 }, + {0, HALF_SQRT_2, 0, HALF_SQRT_2 }, + {0, 0, HALF_SQRT_2, HALF_SQRT_2 }, + {0, -HALF_SQRT_2, HALF_SQRT_2, 0 }, + {0, -HALF_SQRT_2, 0, HALF_SQRT_2 }, + {0, 0, -HALF_SQRT_2, HALF_SQRT_2 } }; + +double generator_diamond_cubic[12][4] = { {1, 0, 0, 0 }, + {0, 1, 0, 0 }, + {0, 0, 1, 0 }, + {0, 0, 0, 1 }, + {0.5, 0.5, 0.5, 0.5 }, + {0.5, 0.5, -0.5, 0.5 }, + {0.5, -0.5, 0.5, 0.5 }, + {0.5, -0.5, -0.5, 0.5 }, + {-0.5, 0.5, 0.5, 0.5 }, + {-0.5, 0.5, -0.5, 0.5 }, + {-0.5, -0.5, 0.5, 0.5 }, + {-0.5, -0.5, -0.5, 0.5 } }; + +double generator_hcp[6][4] = { {1, 0, 0, 0}, + {0.5, 0.5, 0.5, 0.5}, + {0.5, -0.5, -0.5, -0.5}, + {0, SQRT_2_3, -SQRT_1_6, -SQRT_1_6}, + {0, SQRT_1_6, -SQRT_2_3, SQRT_1_6}, + {0, SQRT_1_6, SQRT_1_6, -SQRT_2_3} }; + +double generator_diamond_hexagonal[3][4] = { {1, 0, 0, 0}, + {0.5, 0.5, 0.5, 0.5}, + {0.5, -0.5, -0.5, -0.5} }; + +double generator_icosahedral[60][4] = { {1, 0, 0, 0}, + {HALF_PHI, -HALF_INV_PHI, -0.5, 0}, + {HALF_PHI, 0, -HALF_INV_PHI, -0.5}, + {HALF_PHI, -0.5, 0, -HALF_INV_PHI}, + {HALF_PHI, HALF_INV_PHI, -0.5, 0}, + {HALF_PHI, 0, HALF_INV_PHI, -0.5}, + {HALF_PHI, -0.5, 0, HALF_INV_PHI}, + {HALF_PHI, 0.5, 0, -HALF_INV_PHI}, + {HALF_PHI, 0, -HALF_INV_PHI, 0.5}, + {HALF_PHI, -HALF_INV_PHI, 0.5, 0}, + {HALF_PHI, 0, HALF_INV_PHI, 0.5}, + {HALF_PHI, HALF_INV_PHI, 0.5, 0}, + {HALF_PHI, 0.5, 0, HALF_INV_PHI}, + {0.5, HALF_PHI, -HALF_INV_PHI, 0}, + {0.5, HALF_PHI, HALF_INV_PHI, 0}, + {0.5, 0.5, 0.5, 0.5}, + {0.5, 0.5, 0.5, -0.5}, + {0.5, 0.5, -0.5, 0.5}, + {0.5, 0.5, -0.5, -0.5}, + {0.5, HALF_INV_PHI, 0, HALF_PHI}, + {0.5, HALF_INV_PHI, 0, -HALF_PHI}, + {0.5, 0, HALF_PHI, -HALF_INV_PHI}, + {0.5, 0, HALF_PHI, HALF_INV_PHI}, + {0.5, 0, -HALF_PHI, -HALF_INV_PHI}, + {0.5, 0, -HALF_PHI, HALF_INV_PHI}, + {0.5, -HALF_INV_PHI, 0, HALF_PHI}, + {0.5, -HALF_INV_PHI, 0, -HALF_PHI}, + {0.5, -0.5, 0.5, 0.5}, + {0.5, -0.5, 0.5, -0.5}, + {0.5, -0.5, -0.5, 0.5}, + {0.5, -0.5, -0.5, -0.5}, + {0.5, -HALF_PHI, -HALF_INV_PHI, 0}, + {0.5, -HALF_PHI, HALF_INV_PHI, 0}, + {HALF_INV_PHI, -HALF_PHI, 0, -0.5}, + {HALF_INV_PHI, 0, -0.5, -HALF_PHI}, + {HALF_INV_PHI, -0.5, -HALF_PHI, 0}, + {HALF_INV_PHI, 0, 0.5, -HALF_PHI}, + {HALF_INV_PHI, -HALF_PHI, 0, 0.5}, + {HALF_INV_PHI, 0.5, -HALF_PHI, 0}, + {HALF_INV_PHI, HALF_PHI, 0, -0.5}, + {HALF_INV_PHI, -0.5, HALF_PHI, 0}, + {HALF_INV_PHI, 0, -0.5, HALF_PHI}, + {HALF_INV_PHI, HALF_PHI, 0, 0.5}, + {HALF_INV_PHI, 0, 0.5, HALF_PHI}, + {HALF_INV_PHI, 0.5, HALF_PHI, 0}, + {0, 1, 0, 0}, + {0, HALF_PHI, -0.5, HALF_INV_PHI}, + {0, HALF_PHI, -0.5, -HALF_INV_PHI}, + {0, HALF_PHI, 0.5, HALF_INV_PHI}, + {0, HALF_PHI, 0.5, -HALF_INV_PHI}, + {0, 0.5, HALF_INV_PHI, -HALF_PHI}, + {0, 0.5, HALF_INV_PHI, HALF_PHI}, + {0, 0.5, -HALF_INV_PHI, -HALF_PHI}, + {0, 0.5, -HALF_INV_PHI, HALF_PHI}, + {0, HALF_INV_PHI, -HALF_PHI, 0.5}, + {0, HALF_INV_PHI, -HALF_PHI, -0.5}, + {0, HALF_INV_PHI, HALF_PHI, 0.5}, + {0, HALF_INV_PHI, HALF_PHI, -0.5}, + {0, 0, 1, 0}, + {0, 0, 0, 1} }; + +static void quat_rot(double* r, double* a, double* b) +{ + b[0] = (r[0] * a[0] - r[1] * a[1] - r[2] * a[2] - r[3] * a[3]); + b[1] = (r[0] * a[1] + r[1] * a[0] + r[2] * a[3] - r[3] * a[2]); + b[2] = (r[0] * a[2] - r[1] * a[3] + r[2] * a[0] + r[3] * a[1]); + b[3] = (r[0] * a[3] + r[1] * a[2] - r[2] * a[1] + r[3] * a[0]); +} + +static int rotate_quaternion_into_fundamental_zone(int num_generators, double (*generator)[4], double* q) +{ + double max = 0.0; + int i = 0, bi = -1; + for (i=0;i max) + { + max = t; + bi = i; + } + } + + double f[4]; + quat_rot(q, generator[bi], f); + memcpy(q, &f, 4 * sizeof(double)); + if (q[0] < 0) + { + q[0] = -q[0]; + q[1] = -q[1]; + q[2] = -q[2]; + q[3] = -q[3]; + } + + return bi; +} + +int rotate_quaternion_into_cubic_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(24, generator_cubic, q); +} + +int rotate_quaternion_into_diamond_cubic_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(12, generator_diamond_cubic, q); +} + +int rotate_quaternion_into_icosahedral_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(60, generator_icosahedral, q); +} + +int rotate_quaternion_into_hcp_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(6, generator_hcp, q); +} + +int rotate_quaternion_into_diamond_hexagonal_fundamental_zone(double* q) +{ + return rotate_quaternion_into_fundamental_zone(3, generator_diamond_hexagonal, q); +} + +double quat_dot(double* a, double* b) +{ + return a[0] * b[0] + + a[1] * b[1] + + a[2] * b[2] + + a[3] * b[3]; +} + +double quat_size(double* q) +{ + return sqrt(quat_dot(q, q)); +} + +void normalize_quaternion(double* q) +{ + double size = quat_size(q); + + q[0] /= size; + q[1] /= size; + q[2] /= size; + q[3] /= size; +} + +void rotation_matrix_to_quaternion(double* u, double* q) +{ + double r11 = u[0]; + double r12 = u[1]; + double r13 = u[2]; + double r21 = u[3]; + double r22 = u[4]; + double r23 = u[5]; + double r31 = u[6]; + double r32 = u[7]; + double r33 = u[8]; + + q[0] = (1.0 + r11 + r22 + r33) / 4.0; + q[1] = (1.0 + r11 - r22 - r33) / 4.0; + q[2] = (1.0 - r11 + r22 - r33) / 4.0; + q[3] = (1.0 - r11 - r22 + r33) / 4.0; + + q[0] = sqrt(MAX(0, q[0])); + q[1] = sqrt(MAX(0, q[1])); + q[2] = sqrt(MAX(0, q[2])); + q[3] = sqrt(MAX(0, q[3])); + + double m0 = MAX(q[0], q[1]); + double m1 = MAX(q[2], q[3]); + double max = MAX(m0, m1); + + int i = 0; + for (i=0;i<4;i++) + if (q[i] == max) + break; + + if (i == 0) + { + q[1] *= SIGN(r32 - r23); + q[2] *= SIGN(r13 - r31); + q[3] *= SIGN(r21 - r12); + } + else if (i == 1) + { + q[0] *= SIGN(r32 - r23); + q[2] *= SIGN(r21 + r12); + q[3] *= SIGN(r13 + r31); + } + else if (i == 2) + { + q[0] *= SIGN(r13 - r31); + q[1] *= SIGN(r21 + r12); + q[3] *= SIGN(r32 + r23); + } + else if (i == 3) + { + q[0] *= SIGN(r21 - r12); + q[1] *= SIGN(r31 + r13); + q[2] *= SIGN(r32 + r23); + } + + normalize_quaternion(q); +} + +void quaternion_to_rotation_matrix(double* q, double* u) +{ + double a = q[0]; + double b = q[1]; + double c = q[2]; + double d = q[3]; + + u[0] = a*a + b*b - c*c - d*d; + u[1] = 2*b*c - 2*a*d; + u[2] = 2*b*d + 2*a*c; + + u[3] = 2*b*c + 2*a*d; + u[4] = a*a - b*b + c*c - d*d; + u[5] = 2*c*d - 2*a*b; + + u[6] = 2*b*d - 2*a*c; + u[7] = 2*c*d + 2*a*b; + u[8] = a*a - b*b - c*c + d*d; +} + +double quat_quick_misorientation(double* q1, double* q2) +{ + double t = quat_dot(q1, q2); + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_misorientation(double* q1, double* q2) +{ + return acos(quat_quick_misorientation(q1, q2)); +} + + +double quat_quick_disorientation_cubic(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_cubic_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_cubic(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_cubic(q0, q1)); +} + +double quat_quick_disorientation_diamond_cubic(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_diamond_cubic_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_diamond_cubic(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_diamond_cubic(q0, q1)); +} + +double quat_quick_disorientation_hcp(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_hcp_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_hcp(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_hcp(q0, q1)); +} + +double quat_quick_disorientation_diamond_hexagonal(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_diamond_hexagonal_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_diamond_hexagonal(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_diamond_hexagonal(q0, q1)); +} + +double quat_quick_disorientation_icosahedral(double* q0, double* q1) +{ + double qrot[4]; + double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; + quat_rot(qinv, q1, qrot); + + rotate_quaternion_into_icosahedral_fundamental_zone(qrot); + double t = qrot[0]; + t = MIN(1, MAX(-1, t)); + return 2 * t * t - 1; +} + +double quat_disorientation_icosahedral(double* q0, double* q1) +{ + return acos(quat_quick_disorientation_icosahedral(q0, q1)); +} + diff --git a/src/PTM/ptm_quat.h b/src/PTM/ptm_quat.h new file mode 100644 index 0000000000..381c3ce876 --- /dev/null +++ b/src/PTM/ptm_quat.h @@ -0,0 +1,32 @@ +#ifndef PTM_QUAT_H +#define PTM_QUAT_H + +int rotate_quaternion_into_cubic_fundamental_zone(double* q); +int rotate_quaternion_into_diamond_cubic_fundamental_zone(double* q); +int rotate_quaternion_into_icosahedral_fundamental_zone(double* q); +int rotate_quaternion_into_hcp_fundamental_zone(double* q); +int rotate_quaternion_into_diamond_hexagonal_fundamental_zone(double* q); + +void normalize_quaternion(double* q); +void quaternion_to_rotation_matrix(double* q, double* U); +void rotation_matrix_to_quaternion(double* u, double* q); +double quat_dot(double* a, double* b); +double quat_quick_misorientation(double* q1, double* q2); +double quat_misorientation(double* q1, double* q2); + +double quat_quick_disorientation_cubic(double* q0, double* q1); +double quat_disorientation_cubic(double* q0, double* q1); +double quat_quick_disorientation_diamond_cubic(double* q0, double* q1); +double quat_disorientation_diamond_cubic(double* q0, double* q1); +double quat_quick_disorientation_hcp(double* q0, double* q1); +double quat_disorientation_hcp(double* q0, double* q1); +double quat_quick_disorientation_diamond_hexagonal(double* q0, double* q1); +double quat_disorientation_diamond_hexagonal(double* q0, double* q1); +double quat_quick_disorientation_icosahedral(double* q0, double* q1); +double quat_disorientation_icosahedral(double* q0, double* q1); + +#endif + + + + diff --git a/src/PTM/ptm_structure_matcher.cpp b/src/PTM/ptm_structure_matcher.cpp new file mode 100644 index 0000000000..7eb0a44143 --- /dev/null +++ b/src/PTM/ptm_structure_matcher.cpp @@ -0,0 +1,294 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ptm_convex_hull_incremental.h" +#include "ptm_canonical_coloured.h" +#include "ptm_graph_data.h" +#include "ptm_graph_tools.h" +#include "ptm_normalize_vertices.h" +#include "ptm_polar.h" +#include "ptm_structure_matcher.h" +#include "ptm_constants.h" + + +static double calc_rmsd(int num_points, const double (*ideal_points)[3], double (*normalized)[3], int8_t* mapping, + double G1, double G2, double E0, double* q, double* p_scale) +{ + double A0[9]; + InnerProduct(A0, num_points, ideal_points, normalized, mapping); + + double nrmsdsq, rot[9]; + FastCalcRMSDAndRotation(A0, E0, &nrmsdsq, q, rot); + + double k0 = 0; + for (int i=0;inum_nbrs + 1; + const double (*ideal_points)[3] = s->points; + int8_t inverse_labelling[PTM_MAX_POINTS]; + int8_t mapping[PTM_MAX_POINTS]; + + for (int i=0; inum_graphs;i++) + { + if (hash != s->graphs[i].hash) + continue; + + graph_t* gref = &s->graphs[i]; + for (int j = 0;jnum_automorphisms;j++) + { + for (int k=0;kautomorphism_index + j][k]] = inverse_labelling[ gref->canonical_labelling[k] ]; + + double q[4], scale = 0; + double rmsd = calc_rmsd(num_points, ideal_points, normalized, mapping, G1, G2, E0, q, &scale); + if (rmsd < res->rmsd) + { + res->rmsd = rmsd; + res->scale = scale; + res->ref_struct = s; + memcpy(res->q, q, 4 * sizeof(double)); + memcpy(res->mapping, mapping, sizeof(int8_t) * num_points); + } + } + } +} + +int match_general(const refdata_t* s, double (*ch_points)[3], double (*points)[3], convexhull_t* ch, result_t* res) +{ + int8_t degree[PTM_MAX_NBRS]; + int8_t facets[PTM_MAX_FACETS][3]; + + int ret = get_convex_hull(s->num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); + ch->ok = ret >= 0; + if (ret != 0) + return PTM_NO_ERROR; + + if (ch->num_facets != s->num_facets) + return PTM_NO_ERROR; //incorrect number of facets in convex hull + + int max_degree = graph_degree(s->num_facets, facets, s->num_nbrs, degree); + if (max_degree > s->max_degree) + return PTM_NO_ERROR; + + if (s->type == PTM_MATCH_SC) + for (int i = 0;inum_nbrs;i++) + if (degree[i] != 4) + return PTM_NO_ERROR; + + double normalized[PTM_MAX_POINTS][3]; + subtract_barycentre(s->num_nbrs + 1, points, normalized); + + int8_t code[2 * PTM_MAX_EDGES]; + int8_t colours[PTM_MAX_POINTS] = {0}; + int8_t canonical_labelling[PTM_MAX_POINTS]; + uint64_t hash = 0; + ret = canonical_form_coloured(s->num_facets, facets, s->num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); + if (ret != PTM_NO_ERROR) + return ret; + + check_graphs(s, hash, canonical_labelling, normalized, res); + return PTM_NO_ERROR; +} + +int match_fcc_hcp_ico(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res) +{ + int num_nbrs = structure_fcc.num_nbrs; + int num_facets = structure_fcc.num_facets; + int max_degree = structure_fcc.max_degree; + + int8_t degree[PTM_MAX_NBRS]; + int8_t facets[PTM_MAX_FACETS][3]; + + int ret = get_convex_hull(num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); + ch->ok = ret >= 0; + if (ret != 0) + return PTM_NO_ERROR; + + if (ch->num_facets != num_facets) + return PTM_NO_ERROR; //incorrect number of facets in convex hull + + int _max_degree = graph_degree(num_facets, facets, num_nbrs, degree); + if (_max_degree > max_degree) + return PTM_NO_ERROR; + + double normalized[PTM_MAX_POINTS][3]; + subtract_barycentre(num_nbrs + 1, points, normalized); + + int8_t code[2 * PTM_MAX_EDGES]; + int8_t colours[PTM_MAX_POINTS] = {0}; + int8_t canonical_labelling[PTM_MAX_POINTS]; + uint64_t hash = 0; + ret = canonical_form_coloured(num_facets, facets, num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); + if (ret != PTM_NO_ERROR) + return ret; + + if (flags & PTM_CHECK_FCC) check_graphs(&structure_fcc, hash, canonical_labelling, normalized, res); + if (flags & PTM_CHECK_HCP) check_graphs(&structure_hcp, hash, canonical_labelling, normalized, res); + if (flags & PTM_CHECK_ICO) check_graphs(&structure_ico, hash, canonical_labelling, normalized, res); + return PTM_NO_ERROR; +} + +int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res) +{ + int num_nbrs = structure_dcub.num_nbrs; + int num_facets = structure_fcc.num_facets; + int max_degree = structure_dcub.max_degree; + + + int8_t facets[PTM_MAX_FACETS][3]; + int ret = get_convex_hull(num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); + ch->ok = ret >= 0; + if (ret != 0) + return PTM_NO_ERROR; + + //check for facets with multiple inner atoms + bool inverted[4] = {false, false, false, false}; + for (int i=0;inum_facets;i++) + { + int n = 0; + for (int j=0;j<3;j++) + { + if (facets[i][j] <= 3) + { + inverted[facets[i][j]] = true; + n++; + } + } + if (n > 1) + return PTM_NO_ERROR; + } + + int num_inverted = 0; + for (int i=0;i<4;i++) + num_inverted += inverted[i] ? 1 : 0; + + if (ch->num_facets != num_facets + 2 * num_inverted) + return PTM_NO_ERROR; //incorrect number of facets in convex hull + + int8_t degree[PTM_MAX_NBRS]; + int _max_degree = graph_degree(num_facets, facets, num_nbrs, degree); + if (_max_degree > max_degree) + return PTM_NO_ERROR; + + int num_found = 0; + int8_t toadd[4][3]; + for (int i=0;inum_facets;i++) + { + int a = facets[i][0]; + int b = facets[i][1]; + int c = facets[i][2]; + if (a <= 3 || b <= 3 || c <= 3) + continue; + + int i0 = (a - 4) / 3; + int i1 = (b - 4) / 3; + int i2 = (c - 4) / 3; + + if (i0 == i1 && i0 == i2) + { + if (num_found + num_inverted >= 4) + return PTM_NO_ERROR; + + toadd[num_found][0] = a; + toadd[num_found][1] = b; + toadd[num_found][2] = c; + num_found++; + + memcpy(&facets[i], &facets[ch->num_facets - 1], 3 * sizeof(int8_t)); + ch->num_facets--; + i--; + } + } + + if (num_found + num_inverted != 4) + return PTM_NO_ERROR; + + for (int i=0;inum_facets][0] = i0; + facets[ch->num_facets][1] = b; + facets[ch->num_facets][2] = c; + ch->num_facets++; + + facets[ch->num_facets][0] = a; + facets[ch->num_facets][1] = i0; + facets[ch->num_facets][2] = c; + ch->num_facets++; + + facets[ch->num_facets][0] = a; + facets[ch->num_facets][1] = b; + facets[ch->num_facets][2] = i0; + ch->num_facets++; + } + + _max_degree = graph_degree(ch->num_facets, facets, num_nbrs, degree); + if (_max_degree > max_degree) + return PTM_NO_ERROR; + + double normalized[PTM_MAX_POINTS][3]; + subtract_barycentre(num_nbrs + 1, points, normalized); + + int8_t code[2 * PTM_MAX_EDGES]; + int8_t colours[PTM_MAX_POINTS] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int8_t canonical_labelling[PTM_MAX_POINTS]; + uint64_t hash = 0; + ret = canonical_form_coloured(ch->num_facets, facets, num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); + if (ret != PTM_NO_ERROR) + return ret; + + if (flags & PTM_CHECK_DCUB) check_graphs(&structure_dcub, hash, canonical_labelling, normalized, res); + if (flags & PTM_CHECK_DHEX) check_graphs(&structure_dhex, hash, canonical_labelling, normalized, res); + + return PTM_NO_ERROR; +} + diff --git a/src/PTM/ptm_structure_matcher.h b/src/PTM/ptm_structure_matcher.h new file mode 100644 index 0000000000..4b6f969597 --- /dev/null +++ b/src/PTM/ptm_structure_matcher.h @@ -0,0 +1,21 @@ +#ifndef PTM_STRUCTURE_MATCHER_H +#define PTM_STRUCTURE_MATCHER_H + +#include "ptm_initialize_data.h" +#include "ptm_constants.h" + +typedef struct +{ + double rmsd; + double scale; + double q[4]; //rotation in quaternion form (rigid body transformation) + int8_t mapping[PTM_MAX_POINTS]; + const refdata_t* ref_struct; +} result_t; + +int match_general(const refdata_t* s, double (*ch_points)[3], double (*points)[3], convexhull_t* ch, result_t* res); +int match_fcc_hcp_ico(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); +int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); + +#endif + diff --git a/src/PTM/ptm_voronoi_cell.cpp b/src/PTM/ptm_voronoi_cell.cpp new file mode 100644 index 0000000000..6503ea16c6 --- /dev/null +++ b/src/PTM/ptm_voronoi_cell.cpp @@ -0,0 +1,1368 @@ +// Voro++, a 3D cell-based Voronoi library +// +// Author : Chris H. Rycroft (LBL / UC Berkeley) +// Email : chr@alum.mit.edu +// Date : August 30th 2011 +// +// Modified by PM Larsen for use in Polyhedral Template Matching + +/** \file cell.cc + * \brief Function implementations for the voronoicell and related classes. */ + +#include +#include +#include +#include "ptm_voronoi_config.h" +#include "ptm_voronoi_cell.h" + +namespace voro { + +inline void voro_fatal_error(const char *p,int status) { + fprintf(stderr,"voro++: %s\n",p); + exit(status); + //return -1;//status; +} + +/** Constructs a Voronoi cell and sets up the initial memory. */ +voronoicell_base::voronoicell_base() : + current_vertices(init_vertices), current_vertex_order(init_vertex_order), + current_delete_size(init_delete_size), current_delete2_size(init_delete2_size), + ed(new int*[current_vertices]), nu(new int[current_vertices]), + pts(new double[3*current_vertices]), mem(new int[current_vertex_order]), + mec(new int[current_vertex_order]), mep(new int*[current_vertex_order]), + ds(new int[current_delete_size]), stacke(ds+current_delete_size), + ds2(new int[current_delete2_size]), stacke2(ds2+current_delete_size), + current_marginal(init_marginal), marg(new int[current_marginal]) { + int i; + for(i=0;i<3;i++) { + mem[i]=init_n_vertices;mec[i]=0; + mep[i]=new int[init_n_vertices*((i<<1)+1)]; + } + mem[3]=init_3_vertices;mec[3]=0; + mep[3]=new int[init_3_vertices*7]; + for(i=4;i=0;i--) if(mem[i]>0) delete [] mep[i]; + delete [] marg; + delete [] ds2;delete [] ds; + delete [] mep;delete [] mec; + delete [] mem;delete [] pts; + delete [] nu;delete [] ed; +} + +/** Ensures that enough memory is allocated prior to carrying out a copy. + * \param[in] vc a reference to the specialized version of the calling class. + * \param[in] vb a pointered to the class to be copied. */ +template +void voronoicell_base::check_memory_for_copy(vc_class &vc,voronoicell_base* vb) { + while(current_vertex_ordercurrent_vertex_order) add_memory_vorder(vc); + for(int i=0;imec[i]) add_memory(vc,i,ds2); + while(current_verticesp) add_memory_vertices(vc); +} + +/** Increases the memory storage for a particular vertex order, by increasing + * the size of the of the corresponding mep array. If the arrays already exist, + * their size is doubled; if they don't exist, then new ones of size + * init_n_vertices are allocated. The routine also ensures that the pointers in + * the ed array are updated, by making use of the back pointers. For the cases + * where the back pointer has been temporarily overwritten in the marginal + * vertex code, the auxiliary delete stack is scanned to find out how to update + * the ed value. If the template has been instantiated with the neighbor + * tracking turned on, then the routine also reallocates the corresponding mne + * array. + * \param[in] i the order of the vertex memory to be increased. */ +template +void voronoicell_base::add_memory(vc_class &vc,int i,int *stackp2) { + int s=(i<<1)+1; + if(mem[i]==0) { + vc.n_allocate(i,init_n_vertices); + mep[i]=new int[init_n_vertices*s]; + mem[i]=init_n_vertices; +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Order %d vertex memory created\n",i); +#endif + } else { + int j=0,k,*l; + mem[i]<<=1; + if(mem[i]>max_n_vertices) voro_fatal_error("Point memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Order %d vertex memory scaled up to %d\n",i,mem[i]); +#endif + l=new int[s*mem[i]]; + int m=0; + vc.n_allocate_aux1(i); + while(j=0) { + ed[k]=l+j; + vc.n_set_to_aux1_offset(k,m); + } else { + int *dsp; + for(dsp=ds2;dsp=3 + fputs("Relocated dangling pointer",stderr); +#endif + } + for(k=0;k +void voronoicell_base::add_memory_vertices(vc_class &vc) { + +printf("nope: %d\n", current_vertices); +exit(3); + + int i=(current_vertices<<1),j,**pp,*pnu; + if(i>max_vertices) voro_fatal_error("Vertex memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Vertex memory scaled up to %d\n",i); +#endif + double *ppts; + pp=new int*[i]; + for(j=0;j +void voronoicell_base::add_memory_vorder(vc_class &vc) { + int i=(current_vertex_order<<1),j,*p1,**p2; + if(i>max_vertex_order) voro_fatal_error("Vertex order memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Vertex order memory scaled up to %d\n",i); +#endif + p1=new int[i]; + for(j=0;jmax_delete_size) voro_fatal_error("Delete stack 1 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Delete stack 1 memory scaled up to %d\n",current_delete_size); +#endif + int *dsn=new int[current_delete_size],*dsnp=dsn,*dsp=ds; + while(dspmax_delete2_size) voro_fatal_error("Delete stack 2 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Delete stack 2 memory scaled up to %d\n",current_delete2_size); +#endif + int *dsn=new int[current_delete2_size],*dsnp=dsn,*dsp=ds2; + while(dsp +inline bool voronoicell_base::search_for_outside_edge(vc_class &vc,int &up) { + int i,lp,lw,*j(ds2),*stackp2(ds2); + double l; + *(stackp2++)=up; + while(j +inline void voronoicell_base::add_to_stack(vc_class &vc,int lp,int *&stackp2) { + for(int *k(ds2);k +bool voronoicell_base::nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id) { + int count=0,i,j,k,lp=up,cp,qp,rp,*stackp(ds),*stackp2(ds2),*dsp; + int us=0,ls=0,qs,iqs,cs,uw,qw,lw; + int *edp,*edd; + double u,l,r,q;bool complicated_setup=false,new_double_edge=false,double_edge=false; + + // Initialize the safe testing routine + n_marg=0;px=x;py=y;pz=z;prsq=rsq; + + // Test approximately sqrt(n)/4 points for their proximity to the plane + // and keep the one which is closest + uw=m_test(up,u); + + // Starting from an initial guess, we now move from vertex to vertex, + // to try and find an edge which intersects the cutting plane, + // or a vertex which is on the plane + try { + if(uw==1) { + + // The test point is inside the cutting plane. + us=0; + do { + lp=ed[up][us]; + lw=m_test(lp,l); + if(l=p) throw true; + u=l;up=lp; + for(us=0;us=p) throw true; + u=q;up=qp; + for(us=0;us=1 + fputs("Bailed out of convex calculation\n",stderr); +#endif + qw=1;lw=0; + for(qp=0;qp=current_vertex_order) add_memory_vorder(vc); + if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); + vc.n_set_pointer(p,nu[p]); + ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; + ed[p][nu[p]<<1]=p; + + // Copy the edges of the original vertex into the new + // one. Delete the edges of the original vertex, and + // update the relational table. + us=cycle_down(i,up); + while(i=current_vertex_order) add_memory_vorder(vc); + if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); + + // Copy the edges of the original vertex into the new + // one. Delete the edges of the original vertex, and + // update the relational table. + vc.n_set_pointer(p,nu[p]); + ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; + ed[p][nu[p]<<1]=p; + us=i++; + while(i0) k+=nu[j]; + } else { + if(j>0) { + + // This vertex was visited before, so + // count those vertices to the ones we + // already have. + k+=nu[j]; + + // The only time when we might make a + // duplicate edge is if the point we're + // going to move to next is also a + // marginal point, so test for that + // first. + if(lw==0) { + + // Now see whether this marginal point + // has been visited before. + i=-ed[lp][nu[lp]<<1]; + if(i>0) { + + // Now see if the last edge of that other + // marginal point actually ends up here. + if(ed[i][nu[i]-1]==j) { + new_double_edge=true; + k-=1; + } else new_double_edge=false; + } else { + + // That marginal point hasn't been visited + // before, so we probably don't have to worry + // about duplicate edges, except in the + // case when that's the way into the end + // of the facet, because that way always creates + // an edge. + if(j==rp&&lp==up&&ed[qp][nu[qp]+qs]==us) { + new_double_edge=true; + k-=1; + } else new_double_edge=false; + } + } else new_double_edge=false; + } else { + + // The vertex hasn't been visited + // before, but let's see if it's + // marginal + if(lw==0) { + + // If it is, we need to check + // for the case that it's a + // small branch, and that we're + // heading right back to where + // we came from + i=-ed[lp][nu[lp]<<1]; + if(i==cp) { + new_double_edge=true; + k-=1; + } else new_double_edge=false; + } else new_double_edge=false; + } + } + + // k now holds the number of edges of the new vertex + // we are forming. Add memory for it if it doesn't exist + // already. + while(k>=current_vertex_order) add_memory_vorder(vc); + if(mec[k]==mem[k]) add_memory(vc,k,stackp2); + + // Now create a new vertex with order k, or augment + // the existing one + if(j>0) { + + // If we're augmenting a vertex but we don't + // actually need any more edges, just skip this + // routine to avoid memory confusion + if(nu[j]!=k) { + // Allocate memory and copy the edges + // of the previous instance into it + vc.n_set_aux1(k); + edp=mep[k]+((k<<1)+1)*mec[k]++; + i=0; + while(ids) { + --p; + while(ed[p][nu[p]]==-1) { + j=nu[p]; + edp=ed[p];edd=(mep[j]+((j<<1)+1)*--mec[j]); + while(edp0) voro_fatal_error("Zero order vertex formed",VOROPP_INTERNAL_ERROR); + + // Collapse any order 2 vertices and exit + return collapse_order2(vc); +} + +/** During the creation of a new facet in the plane routine, it is possible + * that some order two vertices may arise. This routine removes them. + * Suppose an order two vertex joins c and d. If there's a edge between + * c and d already, then the order two vertex is just removed; otherwise, + * the order two vertex is removed and c and d are joined together directly. + * It is possible this process will create order two or order one vertices, + * and the routine is continually run until all of them are removed. + * \return False if the vertex removal was unsuccessful, indicative of the cell + * reducing to zero volume and disappearing; true if the vertex removal + * was successful. */ +template +inline bool voronoicell_base::collapse_order2(vc_class &vc) { + if(!collapse_order1(vc)) return false; + int a,b,i,j,k,l; + while(mec[2]>0) { + + // Pick a order 2 vertex and read in its edges + i=--mec[2]; + j=mep[2][5*i];k=mep[2][5*i+1]; + if(j==k) { +#if VOROPP_VERBOSE >=1 + fputs("Order two vertex joins itself",stderr); +#endif + return false; + } + + // Scan the edges of j to see if joins k + for(l=0;l +inline bool voronoicell_base::collapse_order1(vc_class &vc) { + int i,j,k; + while(mec[1]>0) { + up=0; +#if VOROPP_VERBOSE >=1 + fputs("Order one collapse\n",stderr); +#endif + i=--mec[1]; + j=mep[1][3*i];k=mep[1][3*i+1]; + i=mep[1][3*i+2]; + if(!delete_connection(vc,j,k,false)) return false; + --p; + if(up==i) up=0; + if(p!=i) { + if(up==p) up=i; + pts[3*i]=pts[3*p]; + pts[3*i+1]=pts[3*p+1]; + pts[3*i+2]=pts[3*p+2]; + for(k=0;k +inline bool voronoicell_base::delete_connection(vc_class &vc,int j,int k,bool hand) { + int q=hand?k:cycle_up(k,j); + int i=nu[j]-1,l,*edp,*edd,m; +#if VOROPP_VERBOSE >=1 + if(i<1) { + fputs("Zero order vertex formed\n",stderr); + return false; + } +#endif + if(mec[i]==mem[i]) add_memory(vc,i,ds2); + vc.n_set_aux1(i); + for(l=0;l &v) { + double area; + v.clear(); + int i,j,k,l,m,n; + double ux,uy,uz,vx,vy,vz,wx,wy,wz; + for(i=1;i=0) { + area=0; + ed[i][j]=-1-k; + l=cycle_up(ed[i][nu[i]+j],k); + m=ed[k][l];ed[k][l]=-1-m; + while(m!=i) { + n=cycle_up(ed[k][nu[k]+l],m); + ux=pts[3*k]-pts[3*i]; + uy=pts[3*k+1]-pts[3*i+1]; + uz=pts[3*k+2]-pts[3*i+2]; + vx=pts[3*m]-pts[3*i]; + vy=pts[3*m+1]-pts[3*i+1]; + vz=pts[3*m+2]-pts[3*i+2]; + wx=uy*vz-uz*vy; + wy=uz*vx-ux*vz; + wz=ux*vy-uy*vx; + area+=sqrt(wx*wx+wy*wy+wz*wz); + k=m;l=n; + m=ed[k][l];ed[k][l]=-1-m; + } + v.push_back(0.125*area); + } + } + reset_edges(); +} + +/** Several routines in the class that gather cell-based statistics internally + * track their progress by flipping edges to negative so that they know what + * parts of the cell have already been tested. This function resets them back + * to positive. When it is called, it assumes that every edge in the routine + * should have already been flipped to negative, and it bails out with an + * internal error if it encounters a positive edge. */ +inline void voronoicell_base::reset_edges() { + int i,j; + for(i=0;i=0) voro_fatal_error("Edge reset routine found a previously untested edge",VOROPP_INTERNAL_ERROR); + ed[i][j]=-1-ed[i][j]; + } +} + +/** Checks to see if a given vertex is inside, outside or within the test + * plane. If the point is far away from the test plane, the routine immediately + * returns whether it is inside or outside. If the routine is close the the + * plane and within the specified tolerance, then the special check_marginal() + * routine is called. + * \param[in] n the vertex to test. + * \param[out] ans the result of the scalar product used in evaluating the + * location of the point. + * \return -1 if the point is inside the plane, 1 if the point is outside the + * plane, or 0 if the point is within the plane. */ +inline int voronoicell_base::m_test(int n,double &ans) { + double *pp=pts+n+(n<<1); + ans=*(pp++)*px; + ans+=*(pp++)*py; + ans+=*pp*pz-prsq; + if(ans<-tolerance2) { + return -1; + } else if(ans>tolerance2) { + return 1; + } + return check_marginal(n,ans); +} + +/** Checks to see if a given vertex is inside, outside or within the test + * plane, for the case when the point has been detected to be very close to the + * plane. The routine ensures that the returned results are always consistent + * with previous tests, by keeping a table of any marginal results. The routine + * first sees if the vertex is in the table, and if it finds a previously + * computed result it uses that. Otherwise, it computes a result for this + * vertex and adds it the table. + * \param[in] n the vertex to test. + * \param[in] ans the result of the scalar product used in evaluating + * the location of the point. + * \return -1 if the point is inside the plane, 1 if the point is outside the + * plane, or 0 if the point is within the plane. */ +int voronoicell_base::check_marginal(int n,double &ans) { + int i; + for(i=0;imax_marginal) + voro_fatal_error("Marginal case buffer allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); +#if VOROPP_VERBOSE >=2 + fprintf(stderr,"Marginal cases buffer scaled up to %d\n",i); +#endif + int *pmarg=new int[current_marginal]; + for(int j=0;jtolerance?1:(ans<-tolerance?-1:0); + return marg[n_marg-1]; +} + +/** This initializes the class to be a rectangular box. It calls the base class + * initialization routine to set up the edge and vertex information, and then + * sets up the neighbor information, with initial faces being assigned ID + * numbers from -1 to -6. + * \param[in] (xmin,xmax) the minimum and maximum x coordinates. + * \param[in] (ymin,ymax) the minimum and maximum y coordinates. + * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */ +void voronoicell_neighbor::init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) { + init_base(xmin,xmax,ymin,ymax,zmin,zmax); + int *q=mne[3]; + *q=-5;q[1]=-3;q[2]=-1; + q[3]=-5;q[4]=-2;q[5]=-3; + q[6]=-5;q[7]=-1;q[8]=-4; + q[9]=-5;q[10]=-4;q[11]=-2; + q[12]=-6;q[13]=-1;q[14]=-3; + q[15]=-6;q[16]=-3;q[17]=-2; + q[18]=-6;q[19]=-4;q[20]=-1; + q[21]=-6;q[22]=-2;q[23]=-4; + *ne=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9; + ne[4]=q+12;ne[5]=q+15;ne[6]=q+18;ne[7]=q+21; +} + +/** This routine checks to make sure the neighbor information of each face is + * consistent. */ +void voronoicell_neighbor::check_facets() { + int i,j,k,l,m,q; + for(i=1;i=0) { + ed[i][j]=-1-k; + q=ne[i][j]; + l=cycle_up(ed[i][nu[i]+j],k); + do { + m=ed[k][l]; + ed[k][l]=-1-m; + if(ne[k][l]!=q) fprintf(stderr,"Facet error at (%d,%d)=%d, started from (%d,%d)=%d\n",k,l,ne[k][l],i,j,q); + l=cycle_up(ed[k][nu[k]+l],m); + k=m; + } while (k!=i); + } + } + reset_edges(); +} + +/** The class constructor allocates memory for storing neighbor information. */ +voronoicell_neighbor::voronoicell_neighbor() { + int i; + mne=new int*[current_vertex_order]; + ne=new int*[current_vertices]; + for(i=0;i<3;i++) mne[i]=new int[init_n_vertices*i]; + mne[3]=new int[init_3_vertices*3]; + for(i=4;i=0;i--) if(mem[i]>0) delete [] mne[i]; + delete [] mne; + delete [] ne; +} + +/** Computes a vector list of neighbors. */ +void voronoicell_neighbor::neighbors(std::vector &v) { + v.clear(); + int i,j,k,l,m; + for(i=1;i=0) { + v.push_back(ne[i][j]); + ed[i][j]=-1-k; + l=cycle_up(ed[i][nu[i]+j],k); + do { + m=ed[k][l]; + ed[k][l]=-1-m; + l=cycle_up(ed[k][nu[k]+l],m); + k=m; + } while (k!=i); + } + } + reset_edges(); +} + +// Explicit instantiation +template bool voronoicell_base::nplane(voronoicell_neighbor&,double,double,double,double,int); +template void voronoicell_base::check_memory_for_copy(voronoicell_neighbor&,voronoicell_base*); + +} + diff --git a/src/PTM/ptm_voronoi_cell.h b/src/PTM/ptm_voronoi_cell.h new file mode 100644 index 0000000000..80a0501b3c --- /dev/null +++ b/src/PTM/ptm_voronoi_cell.h @@ -0,0 +1,324 @@ +// Voro++, a 3D cell-based Voronoi library +// +// Author : Chris H. Rycroft (LBL / UC Berkeley) +// Email : chr@alum.mit.edu +// Date : August 30th 2011 +// +// Modified by PM Larsen for use in Polyhedral Template Matching + +/** \file cell.hh + * \brief Header file for the voronoicell and related classes. */ + +#ifndef PTM_VOROPP_CELL_HH +#define PTM_VOROPP_CELL_HH + +#include +#include + +#include "ptm_voronoi_config.h" + +namespace voro { + +/** \brief A class representing a single Voronoi cell. + * + * This class represents a single Voronoi cell, as a collection of vertices + * that are connected by edges. The class contains routines for initializing + * the Voronoi cell to be simple shapes such as a box, tetrahedron, or octahedron. + * It the contains routines for recomputing the cell based on cutting it + * by a plane, which forms the key routine for the Voronoi cell computation. + * It contains numerous routine for computing statistics about the Voronoi cell, + * and it can output the cell in several formats. + * + * This class is not intended for direct use, but forms the base of the + * voronoicell and voronoicell_neighbor classes, which extend it based on + * whether neighboring particle ID information needs to be tracked. */ +class voronoicell_base { + public: + /** This holds the current size of the arrays ed and nu, which + * hold the vertex information. If more vertices are created + * than can fit in this array, then it is dynamically extended + * using the add_memory_vertices routine. */ + int current_vertices; + /** This holds the current maximum allowed order of a vertex, + * which sets the size of the mem, mep, and mec arrays. If a + * vertex is created with more vertices than this, the arrays + * are dynamically extended using the add_memory_vorder routine. + */ + int current_vertex_order; + /** This sets the size of the main delete stack. */ + int current_delete_size; + /** This sets the size of the auxiliary delete stack. */ + int current_delete2_size; + /** This sets the total number of vertices in the current cell. + */ + int p; + /** This is the index of particular point in the cell, which is + * used to start the tracing routines for plane intersection + * and cutting. These routines will work starting from any + * point, but it's often most efficient to start from the last + * point considered, since in many cases, the cell construction + * algorithm may consider many planes with similar vectors + * concurrently. */ + int up; + /** This is a two dimensional array that holds information + * about the edge connections of the vertices that make up the + * cell. The two dimensional array is not allocated in the + * usual method. To account for the fact the different vertices + * have different orders, and thus require different amounts of + * storage, the elements of ed[i] point to one-dimensional + * arrays in the mep[] array of different sizes. + * + * More specifically, if vertex i has order m, then ed[i] + * points to a one-dimensional array in mep[m] that has 2*m+1 + * entries. The first m elements hold the neighboring edges, so + * that the jth edge of vertex i is held in ed[i][j]. The next + * m elements hold a table of relations which is redundant but + * helps speed up the computation. It satisfies the relation + * ed[ed[i][j]][ed[i][m+j]]=i. The final entry holds a back + * pointer, so that ed[i+2*m]=i. The back pointers are used + * when rearranging the memory. */ + int **ed; + /** This array holds the order of the vertices in the Voronoi + * cell. This array is dynamically allocated, with its current + * size held by current_vertices. */ + int *nu; + /** This in an array with size 3*current_vertices for holding + * the positions of the vertices. */ + double *pts; + voronoicell_base(); + virtual ~voronoicell_base(); + void init_base(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); + void init_octahedron_base(double l); + void init_tetrahedron_base(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3); + void translate(double x,double y,double z); + double volume(); + double max_radius_squared(); + double total_edge_distance(); + double surface_area(); + void centroid(double &cx,double &cy,double &cz); + int number_of_faces(); + int number_of_edges(); + void vertex_orders(std::vector &v); + void vertices(std::vector &v); + void vertices(double x,double y,double z,std::vector &v); + void face_areas(std::vector &v); + void face_orders(std::vector &v); + void face_freq_table(std::vector &v); + void face_vertices(std::vector &v); + void face_perimeters(std::vector &v); + void normals(std::vector &v); + template + bool nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id); + bool plane_intersects(double x,double y,double z,double rsq); + bool plane_intersects_guess(double x,double y,double z,double rsq); + void construct_relations(); + void check_relations(); + void check_duplicates(); + /** Returns a list of IDs of neighboring particles + * corresponding to each face. + * \param[out] v a reference to a vector in which to return the + * results. If no neighbor information is + * available, a blank vector is returned. */ + virtual void neighbors(std::vector &v) {v.clear();} + /** This a virtual function that is overridden by a routine to + * print the neighboring particle IDs for a given vertex. By + * default, when no neighbor information is available, the + * routine does nothing. + * \param[in] i the vertex to consider. */ + /** This is a simple inline function for picking out the index + * of the next edge counterclockwise at the current vertex. + * \param[in] a the index of an edge of the current vertex. + * \param[in] p the number of the vertex. + * \return 0 if a=nu[p]-1, or a+1 otherwise. */ + inline int cycle_up(int a,int p) {return a==nu[p]-1?0:a+1;} + /** This is a simple inline function for picking out the index + * of the next edge clockwise from the current vertex. + * \param[in] a the index of an edge of the current vertex. + * \param[in] p the number of the vertex. + * \return nu[p]-1 if a=0, or a-1 otherwise. */ + inline int cycle_down(int a,int p) {return a==0?nu[p]-1:a-1;} + protected: + /** This a one dimensional array that holds the current sizes + * of the memory allocations for them mep array.*/ + int *mem; + /** This is a one dimensional array that holds the current + * number of vertices of order p that are stored in the mep[p] + * array. */ + int *mec; + /** This is a two dimensional array for holding the information + * about the edges of the Voronoi cell. mep[p] is a + * one-dimensional array for holding the edge information about + * all vertices of order p, with each vertex holding 2*p+1 + * integers of information. The total number of vertices held + * on mep[p] is stored in mem[p]. If the space runs out, the + * code allocates more using the add_memory() routine. */ + int **mep; + inline void reset_edges(); + template + void check_memory_for_copy(vc_class &vc,voronoicell_base* vb); + void copy(voronoicell_base* vb); + private: + /** This is the delete stack, used to store the vertices which + * are going to be deleted during the plane cutting procedure. + */ + int *ds,*stacke; + /** This is the auxiliary delete stack, which has size set by + * current_delete2_size. */ + int *ds2,*stacke2; + /** This stores the current memory allocation for the marginal + * cases. */ + int current_marginal; + /** This stores the total number of marginal points which are + * currently in the buffer. */ + int n_marg; + /** This array contains a list of the marginal points, and also + * the outcomes of the marginal tests. */ + int *marg; + /** The x coordinate of the normal vector to the test plane. */ + double px; + /** The y coordinate of the normal vector to the test plane. */ + double py; + /** The z coordinate of the normal vector to the test plane. */ + double pz; + /** The magnitude of the normal vector to the test plane. */ + double prsq; + template + void add_memory(vc_class &vc,int i,int *stackp2); + template + void add_memory_vertices(vc_class &vc); + template + void add_memory_vorder(vc_class &vc); + void add_memory_ds(int *&stackp); + void add_memory_ds2(int *&stackp2); + template + inline bool collapse_order1(vc_class &vc); + template + inline bool collapse_order2(vc_class &vc); + template + inline bool delete_connection(vc_class &vc,int j,int k,bool hand); + template + inline bool search_for_outside_edge(vc_class &vc,int &up); + template + inline void add_to_stack(vc_class &vc,int lp,int *&stackp2); + inline bool plane_intersects_track(double x,double y,double z,double rs,double g); + inline void normals_search(std::vector &v,int i,int j,int k); + inline bool search_edge(int l,int &m,int &k); + inline int m_test(int n,double &ans); + int check_marginal(int n,double &ans); + friend class voronoicell; + friend class voronoicell_neighbor; +}; + +/** \brief Extension of the voronoicell_base class to represent a Voronoi cell + * with neighbor information. + * + * This class is an extension of the voronoicell_base class, in cases when the + * IDs of neighboring particles associated with each face of the Voronoi cell. + * It contains additional data structures mne and ne for storing this + * information. */ +class voronoicell_neighbor : public voronoicell_base { + public: + using voronoicell_base::nplane; + /** This two dimensional array holds the neighbor information + * associated with each vertex. mne[p] is a one dimensional + * array which holds all of the neighbor information for + * vertices of order p. */ + int **mne; + /** This is a two dimensional array that holds the neighbor + * information associated with each vertex. ne[i] points to a + * one-dimensional array in mne[nu[i]]. ne[i][j] holds the + * neighbor information associated with the jth edge of vertex + * i. It is set to the ID number of the plane that made the + * face that is clockwise from the jth edge. */ + int **ne; + voronoicell_neighbor(); + ~voronoicell_neighbor(); + void operator=(voronoicell_neighbor &c); + /** Cuts the Voronoi cell by a particle whose center is at a + * separation of (x,y,z) from the cell center. The value of rsq + * should be initially set to \f$x^2+y^2+z^2\f$. + * \param[in] (x,y,z) the normal vector to the plane. + * \param[in] rsq the distance along this vector of the plane. + * \param[in] p_id the plane ID (for neighbor tracking only). + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool nplane(double x,double y,double z,double rsq,int p_id) { + return nplane(*this,x,y,z,rsq,p_id); + } + /** This routine calculates the modulus squared of the vector + * before passing it to the main nplane() routine with full + * arguments. + * \param[in] (x,y,z) the vector to cut the cell by. + * \param[in] p_id the plane ID (for neighbor tracking only). + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool nplane(double x,double y,double z,int p_id) { + double rsq=x*x+y*y+z*z; + return nplane(*this,x,y,z,rsq,p_id); + } + /** This version of the plane routine just makes up the plane + * ID to be zero. It will only be referenced if neighbor + * tracking is enabled. + * \param[in] (x,y,z) the vector to cut the cell by. + * \param[in] rsq the modulus squared of the vector. + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool plane(double x,double y,double z,double rsq) { + return nplane(*this,x,y,z,rsq,0); + } + /** Cuts a Voronoi cell using the influence of a particle at + * (x,y,z), first calculating the modulus squared of this + * vector before passing it to the main nplane() routine. Zero + * is supplied as the plane ID, which will be ignored unless + * neighbor tracking is enabled. + * \param[in] (x,y,z) the vector to cut the cell by. + * \return False if the plane cut deleted the cell entirely, + * true otherwise. */ + inline bool plane(double x,double y,double z) { + double rsq=x*x+y*y+z*z; + return nplane(*this,x,y,z,rsq,0); + } + void init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); + void check_facets(); + virtual void neighbors(std::vector &v); + + private: + int *paux1; + int *paux2; + inline void n_allocate(int i,int m) {mne[i]=new int[m*i];} + inline void n_add_memory_vertices(int i) { + int **pp=new int*[i]; + for(int j=0;j Date: Thu, 20 Sep 2018 00:04:07 -0400 Subject: [PATCH 05/13] Fixed folder structure --- src/PTM/compute_ptm_atom.cpp | 307 --- src/PTM/compute_ptm_atom.h | 48 - src/PTM/ptm_constants.h | 174 -- src/PTM/ptm_functions.h | 27 - src/USER-PTM/alloy_types.cpp | 101 - src/USER-PTM/alloy_types.h | 9 - src/USER-PTM/canonical_coloured.cpp | 167 -- src/USER-PTM/canonical_coloured.h | 9 - src/USER-PTM/cell.cpp | 1368 ----------- src/USER-PTM/cell.h | 324 --- src/USER-PTM/config.h | 129 -- src/USER-PTM/convex_hull_incremental.cpp | 363 --- src/USER-PTM/convex_hull_incremental.h | 27 - src/USER-PTM/deformation_gradient.cpp | 37 - src/USER-PTM/deformation_gradient.h | 142 -- src/USER-PTM/fundamental_mappings.h | 180 -- src/USER-PTM/graph_data.cpp | 2059 ----------------- src/USER-PTM/graph_data.h | 37 - src/USER-PTM/graph_tools.cpp | 52 - src/USER-PTM/graph_tools.h | 11 - src/USER-PTM/index_ptm.cpp | 218 -- src/USER-PTM/initialize_data.cpp | 71 - src/USER-PTM/initialize_data.h | 61 - src/USER-PTM/neighbour_ordering.cpp | 203 -- src/USER-PTM/neighbour_ordering.h | 13 - src/USER-PTM/normalize_vertices.cpp | 55 - src/USER-PTM/normalize_vertices.h | 8 - src/USER-PTM/polar.cpp | 337 --- src/USER-PTM/polar.h | 12 - src/{PTM => USER-PTM}/ptm_alloy_types.cpp | 0 src/{PTM => USER-PTM}/ptm_alloy_types.h | 0 .../ptm_canonical_coloured.cpp | 0 .../ptm_canonical_coloured.h | 0 .../ptm_convex_hull_incremental.cpp | 0 .../ptm_convex_hull_incremental.h | 0 .../ptm_deformation_gradient.cpp | 0 .../ptm_deformation_gradient.h | 0 src/USER-PTM/ptm_functions.h | 2 +- .../ptm_fundamental_mappings.h | 0 src/{PTM => USER-PTM}/ptm_graph_data.cpp | 0 src/{PTM => USER-PTM}/ptm_graph_data.h | 0 src/{PTM => USER-PTM}/ptm_graph_tools.cpp | 0 src/{PTM => USER-PTM}/ptm_graph_tools.h | 0 src/{PTM => USER-PTM}/ptm_index.cpp | 0 src/{PTM => USER-PTM}/ptm_initialize_data.cpp | 0 src/{PTM => USER-PTM}/ptm_initialize_data.h | 0 .../ptm_neighbour_ordering.cpp | 0 .../ptm_neighbour_ordering.h | 0 .../ptm_normalize_vertices.cpp | 0 .../ptm_normalize_vertices.h | 0 src/{PTM => USER-PTM}/ptm_polar.cpp | 0 src/{PTM => USER-PTM}/ptm_polar.h | 0 src/{PTM => USER-PTM}/ptm_quat.cpp | 0 src/{PTM => USER-PTM}/ptm_quat.h | 0 .../ptm_structure_matcher.cpp | 0 src/{PTM => USER-PTM}/ptm_structure_matcher.h | 0 src/{PTM => USER-PTM}/ptm_voronoi_cell.cpp | 0 src/{PTM => USER-PTM}/ptm_voronoi_cell.h | 0 src/{PTM => USER-PTM}/ptm_voronoi_config.h | 0 src/USER-PTM/quat.cpp | 396 ---- src/USER-PTM/quat.h | 32 - src/USER-PTM/structure_matcher.cpp | 294 --- src/USER-PTM/structure_matcher.h | 21 - 63 files changed, 1 insertion(+), 7293 deletions(-) delete mode 100644 src/PTM/compute_ptm_atom.cpp delete mode 100644 src/PTM/compute_ptm_atom.h delete mode 100644 src/PTM/ptm_constants.h delete mode 100644 src/PTM/ptm_functions.h delete mode 100644 src/USER-PTM/alloy_types.cpp delete mode 100644 src/USER-PTM/alloy_types.h delete mode 100644 src/USER-PTM/canonical_coloured.cpp delete mode 100644 src/USER-PTM/canonical_coloured.h delete mode 100644 src/USER-PTM/cell.cpp delete mode 100644 src/USER-PTM/cell.h delete mode 100644 src/USER-PTM/config.h delete mode 100644 src/USER-PTM/convex_hull_incremental.cpp delete mode 100644 src/USER-PTM/convex_hull_incremental.h delete mode 100644 src/USER-PTM/deformation_gradient.cpp delete mode 100644 src/USER-PTM/deformation_gradient.h delete mode 100644 src/USER-PTM/fundamental_mappings.h delete mode 100644 src/USER-PTM/graph_data.cpp delete mode 100644 src/USER-PTM/graph_data.h delete mode 100644 src/USER-PTM/graph_tools.cpp delete mode 100644 src/USER-PTM/graph_tools.h delete mode 100644 src/USER-PTM/index_ptm.cpp delete mode 100644 src/USER-PTM/initialize_data.cpp delete mode 100644 src/USER-PTM/initialize_data.h delete mode 100644 src/USER-PTM/neighbour_ordering.cpp delete mode 100644 src/USER-PTM/neighbour_ordering.h delete mode 100644 src/USER-PTM/normalize_vertices.cpp delete mode 100644 src/USER-PTM/normalize_vertices.h delete mode 100644 src/USER-PTM/polar.cpp delete mode 100644 src/USER-PTM/polar.h rename src/{PTM => USER-PTM}/ptm_alloy_types.cpp (100%) rename src/{PTM => USER-PTM}/ptm_alloy_types.h (100%) rename src/{PTM => USER-PTM}/ptm_canonical_coloured.cpp (100%) rename src/{PTM => USER-PTM}/ptm_canonical_coloured.h (100%) rename src/{PTM => USER-PTM}/ptm_convex_hull_incremental.cpp (100%) rename src/{PTM => USER-PTM}/ptm_convex_hull_incremental.h (100%) rename src/{PTM => USER-PTM}/ptm_deformation_gradient.cpp (100%) rename src/{PTM => USER-PTM}/ptm_deformation_gradient.h (100%) rename src/{PTM => USER-PTM}/ptm_fundamental_mappings.h (100%) rename src/{PTM => USER-PTM}/ptm_graph_data.cpp (100%) rename src/{PTM => USER-PTM}/ptm_graph_data.h (100%) rename src/{PTM => USER-PTM}/ptm_graph_tools.cpp (100%) rename src/{PTM => USER-PTM}/ptm_graph_tools.h (100%) rename src/{PTM => USER-PTM}/ptm_index.cpp (100%) rename src/{PTM => USER-PTM}/ptm_initialize_data.cpp (100%) rename src/{PTM => USER-PTM}/ptm_initialize_data.h (100%) rename src/{PTM => USER-PTM}/ptm_neighbour_ordering.cpp (100%) rename src/{PTM => USER-PTM}/ptm_neighbour_ordering.h (100%) rename src/{PTM => USER-PTM}/ptm_normalize_vertices.cpp (100%) rename src/{PTM => USER-PTM}/ptm_normalize_vertices.h (100%) rename src/{PTM => USER-PTM}/ptm_polar.cpp (100%) rename src/{PTM => USER-PTM}/ptm_polar.h (100%) rename src/{PTM => USER-PTM}/ptm_quat.cpp (100%) rename src/{PTM => USER-PTM}/ptm_quat.h (100%) rename src/{PTM => USER-PTM}/ptm_structure_matcher.cpp (100%) rename src/{PTM => USER-PTM}/ptm_structure_matcher.h (100%) rename src/{PTM => USER-PTM}/ptm_voronoi_cell.cpp (100%) rename src/{PTM => USER-PTM}/ptm_voronoi_cell.h (100%) rename src/{PTM => USER-PTM}/ptm_voronoi_config.h (100%) delete mode 100644 src/USER-PTM/quat.cpp delete mode 100644 src/USER-PTM/quat.h delete mode 100644 src/USER-PTM/structure_matcher.cpp delete mode 100644 src/USER-PTM/structure_matcher.h diff --git a/src/PTM/compute_ptm_atom.cpp b/src/PTM/compute_ptm_atom.cpp deleted file mode 100644 index b6b4a9786c..0000000000 --- a/src/PTM/compute_ptm_atom.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed -under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -/* ---------------------------------------------------------------------- - Contributing author: PM Larsen (MIT) -------------------------------------------------------------------------- */ - -#include -#include -#include -#include - -#include "atom.h" -#include "comm.h" -#include "compute_ptm_atom.h" -#include "error.h" -#include "force.h" -#include "memory.h" -#include "modify.h" -#include "neigh_list.h" -#include "neigh_request.h" -#include "neighbor.h" -#include "pair.h" -#include "update.h" - -#include "ptm_functions.h" - -#define MAX_NEIGHBORS 30 -#define NUM_COLUMNS 7 -#define UNKNOWN 0 -#define OTHER 8 - -using namespace LAMMPS_NS; - -static const char cite_user_ptm_package[] = - "USER-PTM package:\n\n" - "@Article{larsen2016ptm,\n" - " author={Larsen, Peter Mahler and Schmidt, S{\o}ren and Schi{\o}tz, " - "Jakob},\n" - " title={Robust structural identification via polyhedral template " - "matching},\n" - " journal={Modelling~Simul.~Mater.~Sci.~Eng.},\n" - " year={2016},\n" - " number={5},\n" - " volume={24},\n" - " pages={055007},\n" - " DOI = {10.1088/0965-0393/24/5/055007}" - "}\n\n"; - -/* ---------------------------------------------------------------------- */ - -ComputePTMAtom::ComputePTMAtom(LAMMPS *lmp, int narg, char **arg) - : Compute(lmp, narg, arg), list(NULL), output(NULL) { - if (narg != 5) - error->all(FLERR, "Illegal compute ptm/atom command"); - - char *structures = arg[3]; - char *ptr = structures; - - const char *strings[] = {"fcc", "hcp", "bcc", "ico", "sc", - "dcub", "dhex", "all", "default"}; - int32_t flags[] = { - PTM_CHECK_FCC, - PTM_CHECK_HCP, - PTM_CHECK_BCC, - PTM_CHECK_ICO, - PTM_CHECK_SC, - PTM_CHECK_DCUB, - PTM_CHECK_DHEX, - PTM_CHECK_ALL, - PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_BCC | PTM_CHECK_ICO}; - - input_flags = 0; - while (*ptr != '\0') { - - bool found = false; - for (int i = 0; i < 9; i++) { - int len = strlen(strings[i]); - if (strncmp(ptr, strings[i], len) == 0) { - input_flags |= flags[i]; - ptr += len; - found = true; - break; - } - } - - if (!found) - error->all(FLERR, - "Illegal compute ptm/atom command (invalid structure type)"); - - if (*ptr == '\0') - break; - - if (*ptr != '-') - error->all(FLERR, - "Illegal compute ptm/atom command (invalid structure type)"); - - ptr++; - } - - double threshold = force->numeric(FLERR, arg[4]); - if (threshold < 0.0) - error->all(FLERR, - "Illegal compute ptm/atom command (threshold is negative)"); - rmsd_threshold = threshold; - if (rmsd_threshold == 0) - rmsd_threshold = INFINITY; - - peratom_flag = 1; - size_peratom_cols = NUM_COLUMNS; - create_attribute = 1; - nmax = 0; -} - -/* ---------------------------------------------------------------------- */ - -ComputePTMAtom::~ComputePTMAtom() { memory->destroy(output); } - -/* ---------------------------------------------------------------------- */ - -void ComputePTMAtom::init() { - if (force->pair == NULL) - error->all(FLERR, "Compute ptm/atom requires a pair style be defined"); - - int count = 0; - for (int i = 0; i < modify->ncompute; i++) - if (strcmp(modify->compute[i]->style, "ptm/atom") == 0) - count++; - if (count > 1 && comm->me == 0) - error->warning(FLERR, "More than one compute ptm/atom defined"); - - // need an occasional full neighbor list - - int irequest = neighbor->request(this, instance_me); - neighbor->requests[irequest]->pair = 0; - neighbor->requests[irequest]->compute = 1; - neighbor->requests[irequest]->half = 0; - neighbor->requests[irequest]->full = 1; - neighbor->requests[irequest]->occasional = 1; -} - -/* ---------------------------------------------------------------------- */ - -void ComputePTMAtom::init_list(int id, NeighList *ptr) { list = ptr; } - -/* ---------------------------------------------------------------------- */ - -typedef struct { - int index; - double d; -} ptmnbr_t; - -static bool sorthelper_compare(ptmnbr_t const &a, ptmnbr_t const &b) { - return a.d < b.d; -} - -static int get_neighbors(double *pos, int jnum, int *jlist, double **x, - double (*nbr)[3]) { - - ptmnbr_t *nbr_order = new ptmnbr_t[jnum]; - - for (int jj = 0; jj < jnum; jj++) { - int j = jlist[jj]; - j &= NEIGHMASK; - - double dx = pos[0] - x[j][0]; - double dy = pos[1] - x[j][1]; - double dz = pos[2] - x[j][2]; - double rsq = dx * dx + dy * dy + dz * dz; - - nbr_order[jj].index = j; - nbr_order[jj].d = rsq; - } - - std::sort(nbr_order, nbr_order + jnum, &sorthelper_compare); - int num_nbrs = std::min(MAX_NEIGHBORS, jnum); - - nbr[0][0] = nbr[0][1] = nbr[0][2] = 0; - for (int jj = 0; jj < num_nbrs; jj++) { - - int j = nbr_order[jj].index; - nbr[jj + 1][0] = x[j][0] - pos[0]; - nbr[jj + 1][1] = x[j][1] - pos[1]; - nbr[jj + 1][2] = x[j][2] - pos[2]; - } - - delete[] nbr_order; - return num_nbrs; -} - -void ComputePTMAtom::compute_peratom() { - // PTM global initialization. If already initialized this function does - // nothing. - ptm_initialize_global(); - - // initialize PTM local storage - ptm_local_handle_t local_handle = ptm_initialize_local(); - - invoked_peratom = update->ntimestep; - - // grow arrays if necessary - if (atom->nmax > nmax) { - memory->destroy(output); - nmax = atom->nmax; - - memory->create(output, nmax, NUM_COLUMNS, "ptm:ptm_output"); - array_atom = output; - } - - // invoke full neighbor list (will copy or build if necessary) - neighbor->build_one(list); - - int inum = list->inum; - int *ilist = list->ilist; - int *numneigh = list->numneigh; - int **firstneigh = list->firstneigh; - - double **x = atom->x; - int *mask = atom->mask; - int nlocal = atom->nlocal; - - for (int ii = 0; ii < inum; ii++) { - - int i = ilist[ii]; - output[i][0] = UNKNOWN; - if (!(mask[i] & groupbit)) - continue; - - double *pos = x[i]; - - int *jlist = firstneigh[i]; - int jnum = numneigh[i]; - if (jnum <= 0) - continue; - - // get neighbours ordered by increasing distance - double nbr[MAX_NEIGHBORS + 1][3]; - int num_nbrs = get_neighbors(pos, jnum, jlist, x, nbr); - - // check that we have enough neighbours for the desired structure types - int32_t flags = 0; - if (num_nbrs >= PTM_NUM_NBRS_SC && (input_flags & PTM_CHECK_SC)) - flags |= PTM_CHECK_SC; - if (num_nbrs >= PTM_NUM_NBRS_FCC && (input_flags & PTM_CHECK_FCC)) - flags |= PTM_CHECK_FCC; - if (num_nbrs >= PTM_NUM_NBRS_HCP && (input_flags & PTM_CHECK_HCP)) - flags |= PTM_CHECK_HCP; - if (num_nbrs >= PTM_NUM_NBRS_ICO && (input_flags & PTM_CHECK_ICO)) - flags |= PTM_CHECK_ICO; - if (num_nbrs >= PTM_NUM_NBRS_BCC && (input_flags & PTM_CHECK_BCC)) - flags |= PTM_CHECK_BCC; - if (num_nbrs >= PTM_NUM_NBRS_DCUB && (input_flags & PTM_CHECK_DCUB)) - flags |= PTM_CHECK_DCUB; - if (num_nbrs >= PTM_NUM_NBRS_DHEX && (input_flags & PTM_CHECK_DHEX)) - flags |= PTM_CHECK_DHEX; - - // now run PTM - int8_t mapping[MAX_NEIGHBORS + 1]; - int32_t type, alloy_type; - double scale, rmsd, interatomic_distance, lattice_constant; - double q[4], F[9], F_res[3], U[9], P[9]; - ptm_index(local_handle, flags, num_nbrs + 1, nbr, NULL, true, &type, - &alloy_type, &scale, &rmsd, q, F, F_res, U, P, mapping, - &interatomic_distance, &lattice_constant); - - if (rmsd > rmsd_threshold) { - type = PTM_MATCH_NONE; - } - - // printf("%d type=%d rmsd=%f\n", i, type, rmsd); - - if (type == PTM_MATCH_NONE) - type = OTHER; - - output[i][0] = type; - output[i][1] = rmsd; - output[i][2] = interatomic_distance; - output[i][3] = q[0]; - output[i][4] = q[1]; - output[i][5] = q[2]; - output[i][6] = q[3]; - } - - // printf("finished ptm analysis\n"); - ptm_uninitialize_local(local_handle); -} - -/* ---------------------------------------------------------------------- - memory usage of local atom-based array -------------------------------------------------------------------------- */ - -double ComputePTMAtom::memory_usage() { - double bytes = nmax * NUM_COLUMNS * sizeof(double); - bytes += nmax * sizeof(double); - return bytes; -} diff --git a/src/PTM/compute_ptm_atom.h b/src/PTM/compute_ptm_atom.h deleted file mode 100644 index 5c10e0c443..0000000000 --- a/src/PTM/compute_ptm_atom.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifdef COMPUTE_CLASS - -ComputeStyle(ptm/atom,ComputePTMAtom) - -#else - -#ifndef LMP_COMPUTE_PTM_ATOM_H -#define LMP_COMPUTE_PTM_ATOM_H - -#include "compute.h" - -namespace LAMMPS_NS { - -class ComputePTMAtom : public Compute { - public: - ComputePTMAtom(class LAMMPS *, int, char **); - ~ComputePTMAtom(); - void init(); - void init_list(int, class NeighList *); - void compute_peratom(); - double memory_usage(); - - private: - int nmax; - int32_t input_flags; - double rmsd_threshold; - class NeighList *list; - double **output; -}; - -} - -#endif -#endif - diff --git a/src/PTM/ptm_constants.h b/src/PTM/ptm_constants.h deleted file mode 100644 index f868f51e84..0000000000 --- a/src/PTM/ptm_constants.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef PTM_CONSTANTS_H -#define PTM_CONSTANTS_H - -//------------------------------------ -// definitions -//------------------------------------ -#define PTM_NO_ERROR 0 - - -#define PTM_CHECK_FCC (1 << 0) -#define PTM_CHECK_HCP (1 << 1) -#define PTM_CHECK_BCC (1 << 2) -#define PTM_CHECK_ICO (1 << 3) -#define PTM_CHECK_SC (1 << 4) -#define PTM_CHECK_DCUB (1 << 5) -#define PTM_CHECK_DHEX (1 << 6) -#define PTM_CHECK_NONDIAMOND (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC) -#define PTM_CHECK_ALL (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC | PTM_CHECK_DCUB | PTM_CHECK_DHEX) - -#define PTM_MATCH_NONE 0 -#define PTM_MATCH_FCC 1 -#define PTM_MATCH_HCP 2 -#define PTM_MATCH_BCC 3 -#define PTM_MATCH_ICO 4 -#define PTM_MATCH_SC 5 -#define PTM_MATCH_DCUB 6 -#define PTM_MATCH_DHEX 7 - -#define PTM_ALLOY_NONE 0 -#define PTM_ALLOY_PURE 1 -#define PTM_ALLOY_L10 2 -#define PTM_ALLOY_L12_CU 3 -#define PTM_ALLOY_L12_AU 4 -#define PTM_ALLOY_B2 5 -#define PTM_ALLOY_SIC 6 - - -#define PTM_MAX_INPUT_POINTS 35 -#define PTM_MAX_NBRS 16 -#define PTM_MAX_POINTS (PTM_MAX_NBRS + 1) -#define PTM_MAX_FACETS 28 //2 * PTM_MAX_NBRS - 4 -#define PTM_MAX_EDGES 42 //3 * PTM_MAX_NBRS - 6 - - -//------------------------------------ -// number of neighbours -//------------------------------------ -#define PTM_NUM_NBRS_FCC 12 -#define PTM_NUM_NBRS_HCP 12 -#define PTM_NUM_NBRS_BCC 14 -#define PTM_NUM_NBRS_ICO 12 -#define PTM_NUM_NBRS_SC 6 -#define PTM_NUM_NBRS_DCUB 16 -#define PTM_NUM_NBRS_DHEX 16 - -#define PTM_NUM_POINTS_FCC (PTM_NUM_NBRS_FCC + 1) -#define PTM_NUM_POINTS_HCP (PTM_NUM_NBRS_HCP + 1) -#define PTM_NUM_POINTS_BCC (PTM_NUM_NBRS_BCC + 1) -#define PTM_NUM_POINTS_ICO (PTM_NUM_NBRS_ICO + 1) -#define PTM_NUM_POINTS_SC (PTM_NUM_NBRS_SC + 1) -#define PTM_NUM_POINTS_DCUB (PTM_NUM_NBRS_DCUB + 1) -#define PTM_NUM_POINTS_DHEX (PTM_NUM_NBRS_DHEX + 1) - -const int ptm_num_nbrs[8] = {0, PTM_NUM_NBRS_FCC, PTM_NUM_NBRS_HCP, PTM_NUM_NBRS_BCC, PTM_NUM_NBRS_ICO, PTM_NUM_NBRS_SC, PTM_NUM_NBRS_DCUB, PTM_NUM_NBRS_DHEX}; - -//------------------------------------ -// template structures -//------------------------------------ - -//these point sets have barycentre {0, 0, 0} and are scaled such that the mean neighbour distance is 1 - -const double ptm_template_fcc[PTM_NUM_POINTS_FCC][3] = { { 0. , 0. , 0. }, - { 0. , 0.707106781187, 0.707106781187 }, - { 0. , -0.707106781187, -0.707106781187 }, - { 0. , 0.707106781187, -0.707106781187 }, - { 0. , -0.707106781187, 0.707106781187 }, - { 0.707106781187, 0. , 0.707106781187 }, - { -0.707106781187, 0. , -0.707106781187 }, - { 0.707106781187, 0. , -0.707106781187 }, - { -0.707106781187, 0. , 0.707106781187 }, - { 0.707106781187, 0.707106781187, 0. }, - { -0.707106781187, -0.707106781187, 0. }, - { 0.707106781187, -0.707106781187, 0. }, - { -0.707106781187, 0.707106781187, 0. } }; - -const double ptm_template_hcp[PTM_NUM_POINTS_HCP][3] = { { 0. , 0. , 0. }, - { 0.707106781186, 0. , 0.707106781186 }, - { -0.235702260395, -0.942809041583, -0.235702260395 }, - { 0.707106781186, 0.707106781186, 0. }, - { -0.235702260395, -0.235702260395, -0.942809041583 }, - { 0. , 0.707106781186, 0.707106781186 }, - { -0.942809041583, -0.235702260395, -0.235702260395 }, - { -0.707106781186, 0.707106781186, 0. }, - { 0. , 0.707106781186, -0.707106781186 }, - { 0.707106781186, 0. , -0.707106781186 }, - { 0.707106781186, -0.707106781186, 0. }, - { -0.707106781186, 0. , 0.707106781186 }, - { 0. , -0.707106781186, 0.707106781186 } }; - -const double ptm_template_bcc[PTM_NUM_POINTS_BCC][3] = { { 0. , 0. , 0. }, - { -0.541451884327, -0.541451884327, -0.541451884327 }, - { 0.541451884327, 0.541451884327, 0.541451884327 }, - { 0.541451884327, -0.541451884327, -0.541451884327 }, - { -0.541451884327, 0.541451884327, 0.541451884327 }, - { -0.541451884327, 0.541451884327, -0.541451884327 }, - { 0.541451884327, -0.541451884327, 0.541451884327 }, - { -0.541451884327, -0.541451884327, 0.541451884327 }, - { 0.541451884327, 0.541451884327, -0.541451884327 }, - { 0. , 0. , -1.082903768655 }, - { 0. , 0. , 1.082903768655 }, - { 0. , -1.082903768655, 0. }, - { 0. , 1.082903768655, 0. }, - { -1.082903768655, 0. , 0. }, - { 1.082903768655, 0. , 0. } }; - -const double ptm_template_ico[PTM_NUM_POINTS_ICO][3] = { { 0. , 0. , 0. }, - { 0. , 0.525731112119, 0.850650808352 }, - { 0. , -0.525731112119, -0.850650808352 }, - { 0. , 0.525731112119, -0.850650808352 }, - { 0. , -0.525731112119, 0.850650808352 }, - { -0.525731112119, -0.850650808352, 0. }, - { 0.525731112119, 0.850650808352, 0. }, - { 0.525731112119, -0.850650808352, 0. }, - { -0.525731112119, 0.850650808352, 0. }, - { -0.850650808352, 0. , -0.525731112119 }, - { 0.850650808352, 0. , 0.525731112119 }, - { 0.850650808352, 0. , -0.525731112119 }, - { -0.850650808352, 0. , 0.525731112119 } }; - -const double ptm_template_sc[PTM_NUM_POINTS_SC][3] = { { 0. , 0. , 0. }, - { 0. , 0. , -1. }, - { 0. , 0. , 1. }, - { 0. , -1. , 0. }, - { 0. , 1. , 0. }, - { -1. , 0. , 0. }, - { 1. , 0. , 0. } }; - -const double ptm_template_dcub[PTM_NUM_POINTS_DCUB][3] = { { 0. , 0. , 0. }, - { -0.391491627053, 0.391491627053, 0.391491627053 }, - { -0.391491627053, -0.391491627053, -0.391491627053 }, - { 0.391491627053, -0.391491627053, 0.391491627053 }, - { 0.391491627053, 0.391491627053, -0.391491627053 }, - { -0.782983254107, 0. , 0.782983254107 }, - { -0.782983254107, 0.782983254107, 0. }, - { 0. , 0.782983254107, 0.782983254107 }, - { -0.782983254107, -0.782983254107, 0. }, - { -0.782983254107, 0. , -0.782983254107 }, - { 0. , -0.782983254107, -0.782983254107 }, - { 0. , -0.782983254107, 0.782983254107 }, - { 0.782983254107, -0.782983254107, 0. }, - { 0.782983254107, 0. , 0.782983254107 }, - { 0. , 0.782983254107, -0.782983254107 }, - { 0.782983254107, 0. , -0.782983254107 }, - { 0.782983254107, 0.782983254107, 0. } }; - -const double ptm_template_dhex[PTM_NUM_POINTS_DHEX][3] = { { 0. , 0. , 0. }, - { -0.391491627053, -0.391491627053, -0.391491627053 }, - { 0.391491627053, -0.391491627053, 0.391491627053 }, - { -0.391491627053, 0.391491627053, 0.391491627053 }, - { 0.391491627053, 0.391491627053, -0.391491627053 }, - { -0.260994418036, -1.043977672142, -0.260994418036 }, - { -1.043977672142, -0.260994418036, -0.260994418036 }, - { -0.260994418036, -0.260994418036, -1.043977672142 }, - { 0.782983254107, 0. , 0.782983254107 }, - { 0.782983254107, -0.782983254107, 0. }, - { 0. , -0.782983254107, 0.782983254107 }, - { 0. , 0.782983254107, 0.782983254107 }, - { -0.782983254107, 0.782983254107, 0. }, - { -0.782983254107, 0. , 0.782983254107 }, - { 0.782983254107, 0.782983254107, 0. }, - { 0. , 0.782983254107, -0.782983254107 }, - { 0.782983254107, 0. , -0.782983254107 } }; -#endif - diff --git a/src/PTM/ptm_functions.h b/src/PTM/ptm_functions.h deleted file mode 100644 index cd67d4940d..0000000000 --- a/src/PTM/ptm_functions.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef PTM_FUNCTIONS_H -#define PTM_FUNCTIONS_H - -#include -#include -#include "ptm_initialize_data.h" -#include "ptm_constants.h" - - -//------------------------------------ -// function declarations -//------------------------------------ -#ifdef __cplusplus -extern "C" { -#endif - - -int ptm_index( ptm_local_handle_t local_handle, int32_t flags, int num_points, double (*atomic_positions)[3], int32_t* atomic_numbers, bool topological_ordering, //inputs - int32_t* p_type, int32_t* p_alloy_type, double* p_scale, double* p_rmsd, double* q, double* F, double* F_res, double* U, double* P, int8_t* mapping, double* p_interatomic_distance, double* p_lattice_constant); //outputs - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/USER-PTM/alloy_types.cpp b/src/USER-PTM/alloy_types.cpp deleted file mode 100644 index bde51c19b1..0000000000 --- a/src/USER-PTM/alloy_types.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include "ptm_constants.h" -#include "initialize_data.h" - - -#define NUM_ALLOY_TYPES 3 -static uint32_t typedata[NUM_ALLOY_TYPES][3] = { - {PTM_MATCH_FCC, PTM_ALLOY_L10, 0x000001fe}, - {PTM_MATCH_FCC, PTM_ALLOY_L12_CU, 0x0000001e}, - {PTM_MATCH_FCC, PTM_ALLOY_L12_AU, 0x00001ffe}, -}; - -static bool test_pure(int num_nbrs, int32_t* numbers) -{ - for (int i=1;inum_nbrs+1;i++) - binary[i] = numbers[mapping[i]] == numbers[0] ? 0 : 1; - - for (int i=1;inum_nbrs+1;i++) - if (binary[i] != binary[0]) - return false; - - return true; -} - -static int32_t canonical_alloy_representation(const refdata_t* ref, int8_t* mapping, int32_t* numbers) -{ - int8_t binary[PTM_MAX_POINTS]; - for (int i=0;inum_nbrs+1;i++) - binary[i] = numbers[mapping[i]] == numbers[0] ? 0 : 1; - - int8_t temp[PTM_MAX_POINTS]; - uint32_t best = 0xFFFFFFFF; - for (int j=0;jnum_mappings;j++) - { - for (int i=0;inum_nbrs+1;i++) - temp[ref->mapping[j][i]] = binary[i]; - - uint32_t code = 0; - for (int i=0;inum_nbrs+1;i++) - code |= (temp[i] << i); - - best = std::min(best, code); - } - - return best; -} - -int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers) -{ - if (test_pure(ref->num_nbrs, numbers)) - return PTM_ALLOY_PURE; - - if (!test_binary(ref->num_nbrs, numbers)) - return PTM_ALLOY_NONE; - - uint32_t code = canonical_alloy_representation(ref, mapping, numbers); - for (int i=0;itype == typedata[i][0] && code == typedata[i][2]) - return typedata[i][1]; - - if (ref->type == PTM_MATCH_BCC) - if (test_shell_structure(ref, mapping, numbers, 8)) - return PTM_ALLOY_B2; - - if (ref->type == PTM_MATCH_DCUB || ref->type == PTM_MATCH_DHEX) - if (test_shell_structure(ref, mapping, numbers, 4)) - return PTM_ALLOY_SIC; - - return PTM_ALLOY_NONE; -} - diff --git a/src/USER-PTM/alloy_types.h b/src/USER-PTM/alloy_types.h deleted file mode 100644 index 1f2980593a..0000000000 --- a/src/USER-PTM/alloy_types.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef ALLOY_TYPES_H -#define ALLOY_TYPES_H - -#include "initialize_data.h" - -int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers); - -#endif - diff --git a/src/USER-PTM/canonical_coloured.cpp b/src/USER-PTM/canonical_coloured.cpp deleted file mode 100644 index af446e1a95..0000000000 --- a/src/USER-PTM/canonical_coloured.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include -#include "graph_tools.h" -#include "ptm_constants.h" - - -static bool weinberg_coloured(int num_nodes, int num_edges, int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS], int8_t* colours, int8_t* best_code, int8_t* canonical_labelling, int a, int b) -{ - bool m[PTM_MAX_NBRS][PTM_MAX_NBRS]; - memset(m, 0, sizeof(bool) * PTM_MAX_NBRS * PTM_MAX_NBRS); - - int8_t index[PTM_MAX_NBRS]; - memset(index, -1, sizeof(int8_t) * PTM_MAX_NBRS); - - - int n = 0; - index[a] = colours[a] * num_nodes + n++; - if (index[a] > best_code[0]) - return false; - - bool winning = false; - if (index[a] < best_code[0]) - { - best_code[0] = index[a]; - winning = true; - } - - int c = -1; - for (int it=1;it<2*num_edges;it++) - { - bool newvertex = index[b] == -1; - - if (newvertex) - index[b] = colours[b] * num_nodes + n++; - - if (!winning && index[b] > best_code[it]) - return false; - - if (winning || index[b] < best_code[it]) - { - winning = true; - best_code[it] = index[b]; - } - - if (newvertex) - { - //When a new vertex is reached, take the right-most edge - //relative to the edge on which the vertex is reached. - - c = common[a][b]; - } - else if (m[b][a] == false) - { - //When an old vertex is reached on a new path, go back - //in the opposite direction. - - c = a; - } - else - { - //When an old vertex is reached on an old path, leave the - //vertex on the right-most edge that has not previously - //been traversed in that direction. - - c = common[a][b]; - while (m[b][c] == true) - c = common[c][b]; - } - - m[a][b] = true; - a = b; - b = c; - } - - if (winning) - { - memcpy(canonical_labelling, index, sizeof(int8_t) * num_nodes); - return true; - } - - return false; -} - -int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree, int8_t* colours, int8_t* canonical_labelling, int8_t* best_code, uint64_t* p_hash) -{ - int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS] = {{0}}; - int num_edges = 3 * num_facets / 2; - if (!build_facet_map(num_facets, facets, common)) - return -1; - - memset(best_code, SCHAR_MAX, sizeof(int8_t) * 2 * PTM_MAX_EDGES); - - bool equal = true; - for (int i = 1;i=0;i--) - canonical_labelling[i+1] = (canonical_labelling[i] % num_nodes) + 1; - canonical_labelling[0] = 0; - - uint64_t hash = 0; - for (int i = 0;i<2 * num_edges;i++) - { - uint64_t e = best_code[i]; - e += i % 8; - e &= 0xF; - e <<= (4 * i) % 64; - hash ^= e; - } - - *p_hash = hash; - return PTM_NO_ERROR; -} - diff --git a/src/USER-PTM/canonical_coloured.h b/src/USER-PTM/canonical_coloured.h deleted file mode 100644 index 4a7b5f5a4a..0000000000 --- a/src/USER-PTM/canonical_coloured.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CANONICAL_COLOURED_H -#define CANONICAL_COLOURED_H - -#include - -int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree, int8_t* colours, int8_t* canonical_labelling, int8_t* best_code, uint64_t* p_hash); - -#endif - diff --git a/src/USER-PTM/cell.cpp b/src/USER-PTM/cell.cpp deleted file mode 100644 index f88e310b74..0000000000 --- a/src/USER-PTM/cell.cpp +++ /dev/null @@ -1,1368 +0,0 @@ -// Voro++, a 3D cell-based Voronoi library -// -// Author : Chris H. Rycroft (LBL / UC Berkeley) -// Email : chr@alum.mit.edu -// Date : August 30th 2011 -// -// Modified by PM Larsen for use in Polyhedral Template Matching - -/** \file cell.cc - * \brief Function implementations for the voronoicell and related classes. */ - -#include -#include -#include -#include "config.h" -#include "cell.h" - -namespace voro { - -inline void voro_fatal_error(const char *p,int status) { - fprintf(stderr,"voro++: %s\n",p); - exit(status); - //return -1;//status; -} - -/** Constructs a Voronoi cell and sets up the initial memory. */ -voronoicell_base::voronoicell_base() : - current_vertices(init_vertices), current_vertex_order(init_vertex_order), - current_delete_size(init_delete_size), current_delete2_size(init_delete2_size), - ed(new int*[current_vertices]), nu(new int[current_vertices]), - pts(new double[3*current_vertices]), mem(new int[current_vertex_order]), - mec(new int[current_vertex_order]), mep(new int*[current_vertex_order]), - ds(new int[current_delete_size]), stacke(ds+current_delete_size), - ds2(new int[current_delete2_size]), stacke2(ds2+current_delete_size), - current_marginal(init_marginal), marg(new int[current_marginal]) { - int i; - for(i=0;i<3;i++) { - mem[i]=init_n_vertices;mec[i]=0; - mep[i]=new int[init_n_vertices*((i<<1)+1)]; - } - mem[3]=init_3_vertices;mec[3]=0; - mep[3]=new int[init_3_vertices*7]; - for(i=4;i=0;i--) if(mem[i]>0) delete [] mep[i]; - delete [] marg; - delete [] ds2;delete [] ds; - delete [] mep;delete [] mec; - delete [] mem;delete [] pts; - delete [] nu;delete [] ed; -} - -/** Ensures that enough memory is allocated prior to carrying out a copy. - * \param[in] vc a reference to the specialized version of the calling class. - * \param[in] vb a pointered to the class to be copied. */ -template -void voronoicell_base::check_memory_for_copy(vc_class &vc,voronoicell_base* vb) { - while(current_vertex_ordercurrent_vertex_order) add_memory_vorder(vc); - for(int i=0;imec[i]) add_memory(vc,i,ds2); - while(current_verticesp) add_memory_vertices(vc); -} - -/** Increases the memory storage for a particular vertex order, by increasing - * the size of the of the corresponding mep array. If the arrays already exist, - * their size is doubled; if they don't exist, then new ones of size - * init_n_vertices are allocated. The routine also ensures that the pointers in - * the ed array are updated, by making use of the back pointers. For the cases - * where the back pointer has been temporarily overwritten in the marginal - * vertex code, the auxiliary delete stack is scanned to find out how to update - * the ed value. If the template has been instantiated with the neighbor - * tracking turned on, then the routine also reallocates the corresponding mne - * array. - * \param[in] i the order of the vertex memory to be increased. */ -template -void voronoicell_base::add_memory(vc_class &vc,int i,int *stackp2) { - int s=(i<<1)+1; - if(mem[i]==0) { - vc.n_allocate(i,init_n_vertices); - mep[i]=new int[init_n_vertices*s]; - mem[i]=init_n_vertices; -#if VOROPP_VERBOSE >=2 - fprintf(stderr,"Order %d vertex memory created\n",i); -#endif - } else { - int j=0,k,*l; - mem[i]<<=1; - if(mem[i]>max_n_vertices) voro_fatal_error("Point memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); -#if VOROPP_VERBOSE >=2 - fprintf(stderr,"Order %d vertex memory scaled up to %d\n",i,mem[i]); -#endif - l=new int[s*mem[i]]; - int m=0; - vc.n_allocate_aux1(i); - while(j=0) { - ed[k]=l+j; - vc.n_set_to_aux1_offset(k,m); - } else { - int *dsp; - for(dsp=ds2;dsp=3 - fputs("Relocated dangling pointer",stderr); -#endif - } - for(k=0;k -void voronoicell_base::add_memory_vertices(vc_class &vc) { - -printf("nope: %d\n", current_vertices); -exit(3); - - int i=(current_vertices<<1),j,**pp,*pnu; - if(i>max_vertices) voro_fatal_error("Vertex memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); -#if VOROPP_VERBOSE >=2 - fprintf(stderr,"Vertex memory scaled up to %d\n",i); -#endif - double *ppts; - pp=new int*[i]; - for(j=0;j -void voronoicell_base::add_memory_vorder(vc_class &vc) { - int i=(current_vertex_order<<1),j,*p1,**p2; - if(i>max_vertex_order) voro_fatal_error("Vertex order memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); -#if VOROPP_VERBOSE >=2 - fprintf(stderr,"Vertex order memory scaled up to %d\n",i); -#endif - p1=new int[i]; - for(j=0;jmax_delete_size) voro_fatal_error("Delete stack 1 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); -#if VOROPP_VERBOSE >=2 - fprintf(stderr,"Delete stack 1 memory scaled up to %d\n",current_delete_size); -#endif - int *dsn=new int[current_delete_size],*dsnp=dsn,*dsp=ds; - while(dspmax_delete2_size) voro_fatal_error("Delete stack 2 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); -#if VOROPP_VERBOSE >=2 - fprintf(stderr,"Delete stack 2 memory scaled up to %d\n",current_delete2_size); -#endif - int *dsn=new int[current_delete2_size],*dsnp=dsn,*dsp=ds2; - while(dsp -inline bool voronoicell_base::search_for_outside_edge(vc_class &vc,int &up) { - int i,lp,lw,*j(ds2),*stackp2(ds2); - double l; - *(stackp2++)=up; - while(j -inline void voronoicell_base::add_to_stack(vc_class &vc,int lp,int *&stackp2) { - for(int *k(ds2);k -bool voronoicell_base::nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id) { - int count=0,i,j,k,lp=up,cp,qp,rp,*stackp(ds),*stackp2(ds2),*dsp; - int us=0,ls=0,qs,iqs,cs,uw,qw,lw; - int *edp,*edd; - double u,l,r,q;bool complicated_setup=false,new_double_edge=false,double_edge=false; - - // Initialize the safe testing routine - n_marg=0;px=x;py=y;pz=z;prsq=rsq; - - // Test approximately sqrt(n)/4 points for their proximity to the plane - // and keep the one which is closest - uw=m_test(up,u); - - // Starting from an initial guess, we now move from vertex to vertex, - // to try and find an edge which intersects the cutting plane, - // or a vertex which is on the plane - try { - if(uw==1) { - - // The test point is inside the cutting plane. - us=0; - do { - lp=ed[up][us]; - lw=m_test(lp,l); - if(l=p) throw true; - u=l;up=lp; - for(us=0;us=p) throw true; - u=q;up=qp; - for(us=0;us=1 - fputs("Bailed out of convex calculation\n",stderr); -#endif - qw=1;lw=0; - for(qp=0;qp=current_vertex_order) add_memory_vorder(vc); - if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); - vc.n_set_pointer(p,nu[p]); - ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; - ed[p][nu[p]<<1]=p; - - // Copy the edges of the original vertex into the new - // one. Delete the edges of the original vertex, and - // update the relational table. - us=cycle_down(i,up); - while(i=current_vertex_order) add_memory_vorder(vc); - if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); - - // Copy the edges of the original vertex into the new - // one. Delete the edges of the original vertex, and - // update the relational table. - vc.n_set_pointer(p,nu[p]); - ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; - ed[p][nu[p]<<1]=p; - us=i++; - while(i0) k+=nu[j]; - } else { - if(j>0) { - - // This vertex was visited before, so - // count those vertices to the ones we - // already have. - k+=nu[j]; - - // The only time when we might make a - // duplicate edge is if the point we're - // going to move to next is also a - // marginal point, so test for that - // first. - if(lw==0) { - - // Now see whether this marginal point - // has been visited before. - i=-ed[lp][nu[lp]<<1]; - if(i>0) { - - // Now see if the last edge of that other - // marginal point actually ends up here. - if(ed[i][nu[i]-1]==j) { - new_double_edge=true; - k-=1; - } else new_double_edge=false; - } else { - - // That marginal point hasn't been visited - // before, so we probably don't have to worry - // about duplicate edges, except in the - // case when that's the way into the end - // of the facet, because that way always creates - // an edge. - if(j==rp&&lp==up&&ed[qp][nu[qp]+qs]==us) { - new_double_edge=true; - k-=1; - } else new_double_edge=false; - } - } else new_double_edge=false; - } else { - - // The vertex hasn't been visited - // before, but let's see if it's - // marginal - if(lw==0) { - - // If it is, we need to check - // for the case that it's a - // small branch, and that we're - // heading right back to where - // we came from - i=-ed[lp][nu[lp]<<1]; - if(i==cp) { - new_double_edge=true; - k-=1; - } else new_double_edge=false; - } else new_double_edge=false; - } - } - - // k now holds the number of edges of the new vertex - // we are forming. Add memory for it if it doesn't exist - // already. - while(k>=current_vertex_order) add_memory_vorder(vc); - if(mec[k]==mem[k]) add_memory(vc,k,stackp2); - - // Now create a new vertex with order k, or augment - // the existing one - if(j>0) { - - // If we're augmenting a vertex but we don't - // actually need any more edges, just skip this - // routine to avoid memory confusion - if(nu[j]!=k) { - // Allocate memory and copy the edges - // of the previous instance into it - vc.n_set_aux1(k); - edp=mep[k]+((k<<1)+1)*mec[k]++; - i=0; - while(ids) { - --p; - while(ed[p][nu[p]]==-1) { - j=nu[p]; - edp=ed[p];edd=(mep[j]+((j<<1)+1)*--mec[j]); - while(edp0) voro_fatal_error("Zero order vertex formed",VOROPP_INTERNAL_ERROR); - - // Collapse any order 2 vertices and exit - return collapse_order2(vc); -} - -/** During the creation of a new facet in the plane routine, it is possible - * that some order two vertices may arise. This routine removes them. - * Suppose an order two vertex joins c and d. If there's a edge between - * c and d already, then the order two vertex is just removed; otherwise, - * the order two vertex is removed and c and d are joined together directly. - * It is possible this process will create order two or order one vertices, - * and the routine is continually run until all of them are removed. - * \return False if the vertex removal was unsuccessful, indicative of the cell - * reducing to zero volume and disappearing; true if the vertex removal - * was successful. */ -template -inline bool voronoicell_base::collapse_order2(vc_class &vc) { - if(!collapse_order1(vc)) return false; - int a,b,i,j,k,l; - while(mec[2]>0) { - - // Pick a order 2 vertex and read in its edges - i=--mec[2]; - j=mep[2][5*i];k=mep[2][5*i+1]; - if(j==k) { -#if VOROPP_VERBOSE >=1 - fputs("Order two vertex joins itself",stderr); -#endif - return false; - } - - // Scan the edges of j to see if joins k - for(l=0;l -inline bool voronoicell_base::collapse_order1(vc_class &vc) { - int i,j,k; - while(mec[1]>0) { - up=0; -#if VOROPP_VERBOSE >=1 - fputs("Order one collapse\n",stderr); -#endif - i=--mec[1]; - j=mep[1][3*i];k=mep[1][3*i+1]; - i=mep[1][3*i+2]; - if(!delete_connection(vc,j,k,false)) return false; - --p; - if(up==i) up=0; - if(p!=i) { - if(up==p) up=i; - pts[3*i]=pts[3*p]; - pts[3*i+1]=pts[3*p+1]; - pts[3*i+2]=pts[3*p+2]; - for(k=0;k -inline bool voronoicell_base::delete_connection(vc_class &vc,int j,int k,bool hand) { - int q=hand?k:cycle_up(k,j); - int i=nu[j]-1,l,*edp,*edd,m; -#if VOROPP_VERBOSE >=1 - if(i<1) { - fputs("Zero order vertex formed\n",stderr); - return false; - } -#endif - if(mec[i]==mem[i]) add_memory(vc,i,ds2); - vc.n_set_aux1(i); - for(l=0;l &v) { - double area; - v.clear(); - int i,j,k,l,m,n; - double ux,uy,uz,vx,vy,vz,wx,wy,wz; - for(i=1;i=0) { - area=0; - ed[i][j]=-1-k; - l=cycle_up(ed[i][nu[i]+j],k); - m=ed[k][l];ed[k][l]=-1-m; - while(m!=i) { - n=cycle_up(ed[k][nu[k]+l],m); - ux=pts[3*k]-pts[3*i]; - uy=pts[3*k+1]-pts[3*i+1]; - uz=pts[3*k+2]-pts[3*i+2]; - vx=pts[3*m]-pts[3*i]; - vy=pts[3*m+1]-pts[3*i+1]; - vz=pts[3*m+2]-pts[3*i+2]; - wx=uy*vz-uz*vy; - wy=uz*vx-ux*vz; - wz=ux*vy-uy*vx; - area+=sqrt(wx*wx+wy*wy+wz*wz); - k=m;l=n; - m=ed[k][l];ed[k][l]=-1-m; - } - v.push_back(0.125*area); - } - } - reset_edges(); -} - -/** Several routines in the class that gather cell-based statistics internally - * track their progress by flipping edges to negative so that they know what - * parts of the cell have already been tested. This function resets them back - * to positive. When it is called, it assumes that every edge in the routine - * should have already been flipped to negative, and it bails out with an - * internal error if it encounters a positive edge. */ -inline void voronoicell_base::reset_edges() { - int i,j; - for(i=0;i=0) voro_fatal_error("Edge reset routine found a previously untested edge",VOROPP_INTERNAL_ERROR); - ed[i][j]=-1-ed[i][j]; - } -} - -/** Checks to see if a given vertex is inside, outside or within the test - * plane. If the point is far away from the test plane, the routine immediately - * returns whether it is inside or outside. If the routine is close the the - * plane and within the specified tolerance, then the special check_marginal() - * routine is called. - * \param[in] n the vertex to test. - * \param[out] ans the result of the scalar product used in evaluating the - * location of the point. - * \return -1 if the point is inside the plane, 1 if the point is outside the - * plane, or 0 if the point is within the plane. */ -inline int voronoicell_base::m_test(int n,double &ans) { - double *pp=pts+n+(n<<1); - ans=*(pp++)*px; - ans+=*(pp++)*py; - ans+=*pp*pz-prsq; - if(ans<-tolerance2) { - return -1; - } else if(ans>tolerance2) { - return 1; - } - return check_marginal(n,ans); -} - -/** Checks to see if a given vertex is inside, outside or within the test - * plane, for the case when the point has been detected to be very close to the - * plane. The routine ensures that the returned results are always consistent - * with previous tests, by keeping a table of any marginal results. The routine - * first sees if the vertex is in the table, and if it finds a previously - * computed result it uses that. Otherwise, it computes a result for this - * vertex and adds it the table. - * \param[in] n the vertex to test. - * \param[in] ans the result of the scalar product used in evaluating - * the location of the point. - * \return -1 if the point is inside the plane, 1 if the point is outside the - * plane, or 0 if the point is within the plane. */ -int voronoicell_base::check_marginal(int n,double &ans) { - int i; - for(i=0;imax_marginal) - voro_fatal_error("Marginal case buffer allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); -#if VOROPP_VERBOSE >=2 - fprintf(stderr,"Marginal cases buffer scaled up to %d\n",i); -#endif - int *pmarg=new int[current_marginal]; - for(int j=0;jtolerance?1:(ans<-tolerance?-1:0); - return marg[n_marg-1]; -} - -/** This initializes the class to be a rectangular box. It calls the base class - * initialization routine to set up the edge and vertex information, and then - * sets up the neighbor information, with initial faces being assigned ID - * numbers from -1 to -6. - * \param[in] (xmin,xmax) the minimum and maximum x coordinates. - * \param[in] (ymin,ymax) the minimum and maximum y coordinates. - * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */ -void voronoicell_neighbor::init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) { - init_base(xmin,xmax,ymin,ymax,zmin,zmax); - int *q=mne[3]; - *q=-5;q[1]=-3;q[2]=-1; - q[3]=-5;q[4]=-2;q[5]=-3; - q[6]=-5;q[7]=-1;q[8]=-4; - q[9]=-5;q[10]=-4;q[11]=-2; - q[12]=-6;q[13]=-1;q[14]=-3; - q[15]=-6;q[16]=-3;q[17]=-2; - q[18]=-6;q[19]=-4;q[20]=-1; - q[21]=-6;q[22]=-2;q[23]=-4; - *ne=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9; - ne[4]=q+12;ne[5]=q+15;ne[6]=q+18;ne[7]=q+21; -} - -/** This routine checks to make sure the neighbor information of each face is - * consistent. */ -void voronoicell_neighbor::check_facets() { - int i,j,k,l,m,q; - for(i=1;i=0) { - ed[i][j]=-1-k; - q=ne[i][j]; - l=cycle_up(ed[i][nu[i]+j],k); - do { - m=ed[k][l]; - ed[k][l]=-1-m; - if(ne[k][l]!=q) fprintf(stderr,"Facet error at (%d,%d)=%d, started from (%d,%d)=%d\n",k,l,ne[k][l],i,j,q); - l=cycle_up(ed[k][nu[k]+l],m); - k=m; - } while (k!=i); - } - } - reset_edges(); -} - -/** The class constructor allocates memory for storing neighbor information. */ -voronoicell_neighbor::voronoicell_neighbor() { - int i; - mne=new int*[current_vertex_order]; - ne=new int*[current_vertices]; - for(i=0;i<3;i++) mne[i]=new int[init_n_vertices*i]; - mne[3]=new int[init_3_vertices*3]; - for(i=4;i=0;i--) if(mem[i]>0) delete [] mne[i]; - delete [] mne; - delete [] ne; -} - -/** Computes a vector list of neighbors. */ -void voronoicell_neighbor::neighbors(std::vector &v) { - v.clear(); - int i,j,k,l,m; - for(i=1;i=0) { - v.push_back(ne[i][j]); - ed[i][j]=-1-k; - l=cycle_up(ed[i][nu[i]+j],k); - do { - m=ed[k][l]; - ed[k][l]=-1-m; - l=cycle_up(ed[k][nu[k]+l],m); - k=m; - } while (k!=i); - } - } - reset_edges(); -} - -// Explicit instantiation -template bool voronoicell_base::nplane(voronoicell_neighbor&,double,double,double,double,int); -template void voronoicell_base::check_memory_for_copy(voronoicell_neighbor&,voronoicell_base*); - -} - diff --git a/src/USER-PTM/cell.h b/src/USER-PTM/cell.h deleted file mode 100644 index 51a0cbb9ef..0000000000 --- a/src/USER-PTM/cell.h +++ /dev/null @@ -1,324 +0,0 @@ -// Voro++, a 3D cell-based Voronoi library -// -// Author : Chris H. Rycroft (LBL / UC Berkeley) -// Email : chr@alum.mit.edu -// Date : August 30th 2011 -// -// Modified by PM Larsen for use in Polyhedral Template Matching - -/** \file cell.hh - * \brief Header file for the voronoicell and related classes. */ - -#ifndef VOROPP_CELL_HH -#define VOROPP_CELL_HH - -#include -#include - -#include "config.h" - -namespace voro { - -/** \brief A class representing a single Voronoi cell. - * - * This class represents a single Voronoi cell, as a collection of vertices - * that are connected by edges. The class contains routines for initializing - * the Voronoi cell to be simple shapes such as a box, tetrahedron, or octahedron. - * It the contains routines for recomputing the cell based on cutting it - * by a plane, which forms the key routine for the Voronoi cell computation. - * It contains numerous routine for computing statistics about the Voronoi cell, - * and it can output the cell in several formats. - * - * This class is not intended for direct use, but forms the base of the - * voronoicell and voronoicell_neighbor classes, which extend it based on - * whether neighboring particle ID information needs to be tracked. */ -class voronoicell_base { - public: - /** This holds the current size of the arrays ed and nu, which - * hold the vertex information. If more vertices are created - * than can fit in this array, then it is dynamically extended - * using the add_memory_vertices routine. */ - int current_vertices; - /** This holds the current maximum allowed order of a vertex, - * which sets the size of the mem, mep, and mec arrays. If a - * vertex is created with more vertices than this, the arrays - * are dynamically extended using the add_memory_vorder routine. - */ - int current_vertex_order; - /** This sets the size of the main delete stack. */ - int current_delete_size; - /** This sets the size of the auxiliary delete stack. */ - int current_delete2_size; - /** This sets the total number of vertices in the current cell. - */ - int p; - /** This is the index of particular point in the cell, which is - * used to start the tracing routines for plane intersection - * and cutting. These routines will work starting from any - * point, but it's often most efficient to start from the last - * point considered, since in many cases, the cell construction - * algorithm may consider many planes with similar vectors - * concurrently. */ - int up; - /** This is a two dimensional array that holds information - * about the edge connections of the vertices that make up the - * cell. The two dimensional array is not allocated in the - * usual method. To account for the fact the different vertices - * have different orders, and thus require different amounts of - * storage, the elements of ed[i] point to one-dimensional - * arrays in the mep[] array of different sizes. - * - * More specifically, if vertex i has order m, then ed[i] - * points to a one-dimensional array in mep[m] that has 2*m+1 - * entries. The first m elements hold the neighboring edges, so - * that the jth edge of vertex i is held in ed[i][j]. The next - * m elements hold a table of relations which is redundant but - * helps speed up the computation. It satisfies the relation - * ed[ed[i][j]][ed[i][m+j]]=i. The final entry holds a back - * pointer, so that ed[i+2*m]=i. The back pointers are used - * when rearranging the memory. */ - int **ed; - /** This array holds the order of the vertices in the Voronoi - * cell. This array is dynamically allocated, with its current - * size held by current_vertices. */ - int *nu; - /** This in an array with size 3*current_vertices for holding - * the positions of the vertices. */ - double *pts; - voronoicell_base(); - virtual ~voronoicell_base(); - void init_base(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); - void init_octahedron_base(double l); - void init_tetrahedron_base(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3); - void translate(double x,double y,double z); - double volume(); - double max_radius_squared(); - double total_edge_distance(); - double surface_area(); - void centroid(double &cx,double &cy,double &cz); - int number_of_faces(); - int number_of_edges(); - void vertex_orders(std::vector &v); - void vertices(std::vector &v); - void vertices(double x,double y,double z,std::vector &v); - void face_areas(std::vector &v); - void face_orders(std::vector &v); - void face_freq_table(std::vector &v); - void face_vertices(std::vector &v); - void face_perimeters(std::vector &v); - void normals(std::vector &v); - template - bool nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id); - bool plane_intersects(double x,double y,double z,double rsq); - bool plane_intersects_guess(double x,double y,double z,double rsq); - void construct_relations(); - void check_relations(); - void check_duplicates(); - /** Returns a list of IDs of neighboring particles - * corresponding to each face. - * \param[out] v a reference to a vector in which to return the - * results. If no neighbor information is - * available, a blank vector is returned. */ - virtual void neighbors(std::vector &v) {v.clear();} - /** This a virtual function that is overridden by a routine to - * print the neighboring particle IDs for a given vertex. By - * default, when no neighbor information is available, the - * routine does nothing. - * \param[in] i the vertex to consider. */ - /** This is a simple inline function for picking out the index - * of the next edge counterclockwise at the current vertex. - * \param[in] a the index of an edge of the current vertex. - * \param[in] p the number of the vertex. - * \return 0 if a=nu[p]-1, or a+1 otherwise. */ - inline int cycle_up(int a,int p) {return a==nu[p]-1?0:a+1;} - /** This is a simple inline function for picking out the index - * of the next edge clockwise from the current vertex. - * \param[in] a the index of an edge of the current vertex. - * \param[in] p the number of the vertex. - * \return nu[p]-1 if a=0, or a-1 otherwise. */ - inline int cycle_down(int a,int p) {return a==0?nu[p]-1:a-1;} - protected: - /** This a one dimensional array that holds the current sizes - * of the memory allocations for them mep array.*/ - int *mem; - /** This is a one dimensional array that holds the current - * number of vertices of order p that are stored in the mep[p] - * array. */ - int *mec; - /** This is a two dimensional array for holding the information - * about the edges of the Voronoi cell. mep[p] is a - * one-dimensional array for holding the edge information about - * all vertices of order p, with each vertex holding 2*p+1 - * integers of information. The total number of vertices held - * on mep[p] is stored in mem[p]. If the space runs out, the - * code allocates more using the add_memory() routine. */ - int **mep; - inline void reset_edges(); - template - void check_memory_for_copy(vc_class &vc,voronoicell_base* vb); - void copy(voronoicell_base* vb); - private: - /** This is the delete stack, used to store the vertices which - * are going to be deleted during the plane cutting procedure. - */ - int *ds,*stacke; - /** This is the auxiliary delete stack, which has size set by - * current_delete2_size. */ - int *ds2,*stacke2; - /** This stores the current memory allocation for the marginal - * cases. */ - int current_marginal; - /** This stores the total number of marginal points which are - * currently in the buffer. */ - int n_marg; - /** This array contains a list of the marginal points, and also - * the outcomes of the marginal tests. */ - int *marg; - /** The x coordinate of the normal vector to the test plane. */ - double px; - /** The y coordinate of the normal vector to the test plane. */ - double py; - /** The z coordinate of the normal vector to the test plane. */ - double pz; - /** The magnitude of the normal vector to the test plane. */ - double prsq; - template - void add_memory(vc_class &vc,int i,int *stackp2); - template - void add_memory_vertices(vc_class &vc); - template - void add_memory_vorder(vc_class &vc); - void add_memory_ds(int *&stackp); - void add_memory_ds2(int *&stackp2); - template - inline bool collapse_order1(vc_class &vc); - template - inline bool collapse_order2(vc_class &vc); - template - inline bool delete_connection(vc_class &vc,int j,int k,bool hand); - template - inline bool search_for_outside_edge(vc_class &vc,int &up); - template - inline void add_to_stack(vc_class &vc,int lp,int *&stackp2); - inline bool plane_intersects_track(double x,double y,double z,double rs,double g); - inline void normals_search(std::vector &v,int i,int j,int k); - inline bool search_edge(int l,int &m,int &k); - inline int m_test(int n,double &ans); - int check_marginal(int n,double &ans); - friend class voronoicell; - friend class voronoicell_neighbor; -}; - -/** \brief Extension of the voronoicell_base class to represent a Voronoi cell - * with neighbor information. - * - * This class is an extension of the voronoicell_base class, in cases when the - * IDs of neighboring particles associated with each face of the Voronoi cell. - * It contains additional data structures mne and ne for storing this - * information. */ -class voronoicell_neighbor : public voronoicell_base { - public: - using voronoicell_base::nplane; - /** This two dimensional array holds the neighbor information - * associated with each vertex. mne[p] is a one dimensional - * array which holds all of the neighbor information for - * vertices of order p. */ - int **mne; - /** This is a two dimensional array that holds the neighbor - * information associated with each vertex. ne[i] points to a - * one-dimensional array in mne[nu[i]]. ne[i][j] holds the - * neighbor information associated with the jth edge of vertex - * i. It is set to the ID number of the plane that made the - * face that is clockwise from the jth edge. */ - int **ne; - voronoicell_neighbor(); - ~voronoicell_neighbor(); - void operator=(voronoicell_neighbor &c); - /** Cuts the Voronoi cell by a particle whose center is at a - * separation of (x,y,z) from the cell center. The value of rsq - * should be initially set to \f$x^2+y^2+z^2\f$. - * \param[in] (x,y,z) the normal vector to the plane. - * \param[in] rsq the distance along this vector of the plane. - * \param[in] p_id the plane ID (for neighbor tracking only). - * \return False if the plane cut deleted the cell entirely, - * true otherwise. */ - inline bool nplane(double x,double y,double z,double rsq,int p_id) { - return nplane(*this,x,y,z,rsq,p_id); - } - /** This routine calculates the modulus squared of the vector - * before passing it to the main nplane() routine with full - * arguments. - * \param[in] (x,y,z) the vector to cut the cell by. - * \param[in] p_id the plane ID (for neighbor tracking only). - * \return False if the plane cut deleted the cell entirely, - * true otherwise. */ - inline bool nplane(double x,double y,double z,int p_id) { - double rsq=x*x+y*y+z*z; - return nplane(*this,x,y,z,rsq,p_id); - } - /** This version of the plane routine just makes up the plane - * ID to be zero. It will only be referenced if neighbor - * tracking is enabled. - * \param[in] (x,y,z) the vector to cut the cell by. - * \param[in] rsq the modulus squared of the vector. - * \return False if the plane cut deleted the cell entirely, - * true otherwise. */ - inline bool plane(double x,double y,double z,double rsq) { - return nplane(*this,x,y,z,rsq,0); - } - /** Cuts a Voronoi cell using the influence of a particle at - * (x,y,z), first calculating the modulus squared of this - * vector before passing it to the main nplane() routine. Zero - * is supplied as the plane ID, which will be ignored unless - * neighbor tracking is enabled. - * \param[in] (x,y,z) the vector to cut the cell by. - * \return False if the plane cut deleted the cell entirely, - * true otherwise. */ - inline bool plane(double x,double y,double z) { - double rsq=x*x+y*y+z*z; - return nplane(*this,x,y,z,rsq,0); - } - void init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); - void check_facets(); - virtual void neighbors(std::vector &v); - - private: - int *paux1; - int *paux2; - inline void n_allocate(int i,int m) {mne[i]=new int[m*i];} - inline void n_add_memory_vertices(int i) { - int **pp=new int*[i]; - for(int j=0;j -#include -#include -#include -#include -#include "convex_hull_incremental.h" -#include "ptm_constants.h" - - -#define VISIBLE 1 -#define INVISIBLE 2 -#define BOTH 3 -#define TOLERANCE 1E-8 - -static double norm_squared(double* p) -{ - double x = p[0]; - double y = p[1]; - double z = p[2]; - - return x*x + y*y + z*z; -} - -static double dot_product(const double* a, const double* b) -{ - return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; -} - -static void cross_product(double* a, double* b, double* c) -{ - c[0] = a[1] * b[2] - a[2] * b[1]; - c[1] = a[2] * b[0] - a[0] * b[2]; - c[2] = a[0] * b[1] - a[1] * b[0]; -} - -static void calculate_plane_normal(const double (*points)[3], int a, int b, int c, double* plane_normal) -{ - double u[3] = { points[b][0] - points[a][0], - points[b][1] - points[a][1], - points[b][2] - points[a][2] }; - - double v[3] = { points[c][0] - points[a][0], - points[c][1] - points[a][1], - points[c][2] - points[a][2] }; - - cross_product(u, v, plane_normal); - double norm = sqrt(norm_squared(plane_normal)); - plane_normal[0] /= norm; - plane_normal[1] /= norm; - plane_normal[2] /= norm; -} - -static double point_plane_distance(const double* w, const double* plane_point, const double* plane_cross) -{ - return plane_cross[0] * (plane_point[0] - w[0]) - + plane_cross[1] * (plane_point[1] - w[1]) - + plane_cross[2] * (plane_point[2] - w[2]); -} - -static bool calc_max_extent(int num_points, const double (*points)[3], int* min_index, int* max_index) -{ - for (int j=0;j<3;j++) - { - double dmin = DBL_MAX, dmax = -DBL_MAX; - int imin = 0, imax = 0; - - for (int i = 0;i dmax) - { - dmax = d; - imax = i; - } - } - - if (imin == imax) - return false; //degenerate point set - - min_index[j] = imin; - max_index[j] = imax; - } - - return true; -} - -static bool find_third_point(int num_points, const double (*points)[3], int a, int b, int* p_c) -{ - const double* x1 = points[a]; - const double* x2 = points[b]; - - double x2x1[3] = {x2[0] - x1[0], x2[1] - x1[1], x2[2] - x1[2]}; - double ns_x2x1 = norm_squared(x2x1); - - int bi = -1; - double max_dist = 0.0; - for (int i = 0;i max_dist) - { - max_dist = dist; - bi = i; - } - } - - *p_c = bi; - return max_dist > TOLERANCE; -} - -static bool find_fourth_point(int num_points, const double (*points)[3], int a, int b, int c, int* p_d) -{ - double plane_normal[3]; - calculate_plane_normal(points, a, b, c, plane_normal); - - - int bi = -1; - double max_dist = 0.0; - for (int i = 0;i max_dist) - { - max_dist = dist; - bi = i; - } - } - - *p_d = bi; - return max_dist > TOLERANCE; -} - -static int initial_simplex(int num_points, const double (*points)[3], int* initial_vertices) -{ - int min_index[3] = {0}; - int max_index[3] = {0}; - if (!calc_max_extent(num_points, points, min_index, max_index)) - return -1; - - int bi = -1; - double max_dist = 0.0; - for (int i = 0;i<3;i++) - { - int a = min_index[i], b = max_index[i]; - double delta[3] = { points[a][0] - points[b][0], - points[a][1] - points[b][1], - points[a][2] - points[b][2] }; - double dist = norm_squared(delta); - if (dist > max_dist) - { - bi = i; - max_dist = dist; - } - } - - //first two points are (a, b) - int a = min_index[bi], b = max_index[bi], c = -1, d = -1; - - if (!find_third_point(num_points, points, a, b, &c)) - return -2; - - if (!find_fourth_point(num_points, points, a, b, c, &d)) - return -3; - - initial_vertices[0] = a; - initial_vertices[1] = b; - initial_vertices[2] = c; - initial_vertices[3] = d; - return 0; -} - -static bool visible(const double* w, const double* plane_point, const double* plane_normal) -{ - return point_plane_distance(w, plane_point, plane_normal) > 0; -} - -void add_facet(const double (*points)[3], int a, int b, int c, int8_t* facet, double* plane_normal, double* barycentre) -{ - calculate_plane_normal(points, a, b, c, plane_normal); - if (visible(barycentre, points[a], plane_normal)) - { - plane_normal[0] = -plane_normal[0]; - plane_normal[1] = -plane_normal[1]; - plane_normal[2] = -plane_normal[2]; - - facet[0] = b; - facet[1] = a; - facet[2] = c; - } - else - { - facet[0] = a; - facet[1] = b; - facet[2] = c; - } -} - -static int initialize_convex_hull(int num_points, const double (*points)[3], int8_t facets[][3], double plane_normal[][3], bool* processed, int* initial_vertices, double* barycentre) -{ - memset(processed, 0, PTM_MAX_POINTS * sizeof(bool)); - memset(barycentre, 0, 3 * sizeof(double)); - int ret = initial_simplex(num_points, points, initial_vertices); - if (ret != 0) - return ret; - - for (int i = 0;i<4;i++) - { - int a = initial_vertices[i]; - processed[a] = true; - - barycentre[0] += points[a][0]; - barycentre[1] += points[a][1]; - barycentre[2] += points[a][2]; - } - barycentre[0] /= 4; - barycentre[1] /= 4; - barycentre[2] /= 4; - - add_facet(points, initial_vertices[0], initial_vertices[1], initial_vertices[2], facets[0], plane_normal[0], barycentre); - add_facet(points, initial_vertices[0], initial_vertices[1], initial_vertices[3], facets[1], plane_normal[1], barycentre); - add_facet(points, initial_vertices[0], initial_vertices[2], initial_vertices[3], facets[2], plane_normal[2], barycentre); - add_facet(points, initial_vertices[1], initial_vertices[2], initial_vertices[3], facets[3], plane_normal[3], barycentre); - return 0; -} - -int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, int8_t simplex[][3]) -{ - assert( num_points == PTM_NUM_POINTS_FCC - || num_points == PTM_NUM_POINTS_HCP - || num_points == PTM_NUM_POINTS_BCC - || num_points == PTM_NUM_POINTS_ICO - || num_points == PTM_NUM_POINTS_SC - || num_points == PTM_NUM_POINTS_DCUB - || num_points == PTM_NUM_POINTS_DHEX); - - int ret = 0; - int num_prev = ch->num_prev; - ch->num_prev = num_points; - if (!ch->ok || 0) - { - ret = initialize_convex_hull(num_points, points, ch->facets, ch->plane_normal, ch->processed, ch->initial_vertices, ch->barycentre); - if (ret != 0) - return ret; - - ch->num_facets = 4; - num_prev = 0; - } - - for (int i = num_prev;iprocessed[i]) - continue; - ch->processed[i] = true; - - int num_to_add = 0; - int8_t to_add[PTM_MAX_FACETS][3]; - int8_t edge_visible[PTM_MAX_POINTS][PTM_MAX_POINTS]; - memset(edge_visible, 0, sizeof(int8_t) * PTM_MAX_POINTS * PTM_MAX_POINTS); - for (int j = 0;jnum_facets;j++) - { - int a = ch->facets[j][0]; - int b = ch->facets[j][1]; - int c = ch->facets[j][2]; - - int u = 0, v = 0, w = 0; - - double distance = point_plane_distance(points[i], points[a], ch->plane_normal[j]); - bool vis = distance > TOLERANCE; - if (vis) - { - u = edge_visible[a][b] |= VISIBLE; - edge_visible[b][a] |= VISIBLE; - - v = edge_visible[b][c] |= VISIBLE; - edge_visible[c][b] |= VISIBLE; - - w = edge_visible[c][a] |= VISIBLE; - edge_visible[a][c] |= VISIBLE; - - memcpy(ch->facets[j], ch->facets[ch->num_facets-1], 3 * sizeof(int8_t)); - memcpy(ch->plane_normal[j], ch->plane_normal[ch->num_facets-1], 3 * sizeof(double)); - ch->num_facets--; - j--; - } - else - { - u = edge_visible[a][b] |= INVISIBLE; - edge_visible[b][a] |= INVISIBLE; - - v = edge_visible[b][c] |= INVISIBLE; - edge_visible[c][b] |= INVISIBLE; - - w = edge_visible[c][a] |= INVISIBLE; - edge_visible[a][c] |= INVISIBLE; - } - - if (u == BOTH) - { - to_add[num_to_add][0] = i; - to_add[num_to_add][1] = a; - to_add[num_to_add][2] = b; - num_to_add++; - } - - if (v == BOTH) - { - to_add[num_to_add][0] = i; - to_add[num_to_add][1] = b; - to_add[num_to_add][2] = c; - num_to_add++; - } - - if (w == BOTH) - { - to_add[num_to_add][0] = i; - to_add[num_to_add][1] = c; - to_add[num_to_add][2] = a; - num_to_add++; - } - } - - for (int j = 0;jnum_facets >= PTM_MAX_FACETS) - return -4; - - add_facet(points, to_add[j][0], to_add[j][1], to_add[j][2], ch->facets[ch->num_facets], ch->plane_normal[ch->num_facets], ch->barycentre); ch->num_facets++; - } - } - - for (int i=0;inum_facets;i++) - { - int a = ch->facets[i][0]; - int b = ch->facets[i][1]; - int c = ch->facets[i][2]; - if (a == 0 || b == 0 || c == 0) - return 1; //central atom contained in convex hull - - simplex[i][0] = a - 1; - simplex[i][1] = b - 1; - simplex[i][2] = c - 1; - } - - return ret; -} - diff --git a/src/USER-PTM/convex_hull_incremental.h b/src/USER-PTM/convex_hull_incremental.h deleted file mode 100644 index d384a0457e..0000000000 --- a/src/USER-PTM/convex_hull_incremental.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CONVEX_HULL_INCREMENTAL_H -#define CONVEX_HULL_INCREMENTAL_H - - -#include -#include -#include "ptm_constants.h" - - -typedef struct -{ - int8_t facets[PTM_MAX_FACETS][3]; - double plane_normal[PTM_MAX_FACETS][3]; - bool processed[PTM_MAX_POINTS]; - int initial_vertices[4]; - double barycentre[3]; - int num_facets; - int num_prev; - bool ok; - -} convexhull_t; - -void add_facet(const double (*points)[3], int a, int b, int c, int8_t* facet, double* plane_normal, double* barycentre); -int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, int8_t simplex[][3]); - -#endif - diff --git a/src/USER-PTM/deformation_gradient.cpp b/src/USER-PTM/deformation_gradient.cpp deleted file mode 100644 index 9a86dff6a3..0000000000 --- a/src/USER-PTM/deformation_gradient.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "deformation_gradient.h" - - -void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res) -{ - for (int i = 0;i<3;i++) - { - for (int j = 0;j<3;j++) - { - double acc = 0.0; - for (int k = 0;k -#include "ptm_constants.h" - -void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res); - -//sc -#define k_sc 0.5 -const double penrose_sc[PTM_NUM_POINTS_SC][3] = { - {0, 0, 0}, - {0, 0, -k_sc}, - {0, 0, k_sc}, - {0, -k_sc, 0}, - {0, k_sc, 0}, - {-k_sc, 0, 0}, - {k_sc, 0, 0}, - }; - -//fcc -#define k_fcc 0.17677669529663678216 -const double penrose_fcc[PTM_NUM_POINTS_FCC][3] = { - {0, 0, 0}, - {0, k_fcc, k_fcc}, - {0, -k_fcc, -k_fcc}, - {0, k_fcc, -k_fcc}, - {0, -k_fcc, k_fcc}, - {k_fcc, 0, k_fcc}, - {-k_fcc, 0, -k_fcc}, - {k_fcc, 0, -k_fcc}, - {-k_fcc, 0, k_fcc}, - {k_fcc, k_fcc, -0}, - {-k_fcc, -k_fcc, 0}, - {k_fcc, -k_fcc, 0}, - {-k_fcc, k_fcc, -0}, - }; - -//hcp -#define k_hcp 0.17677669529663678216 -const double penrose_hcp[PTM_NUM_POINTS_HCP][3] = { - {0, 0, 0}, - {k_hcp, 0, k_hcp}, - {-k_hcp/3, -4*k_hcp/3, -k_hcp/3}, - {k_hcp, k_hcp, 0}, - {-k_hcp/3, -k_hcp/3, -4*k_hcp/3}, - {0, k_hcp, k_hcp}, - {-4*k_hcp/3, -k_hcp/3, -k_hcp/3}, - {-k_hcp, k_hcp, -0}, - {0, k_hcp, -k_hcp}, - {k_hcp, 0, -k_hcp}, - {k_hcp, -k_hcp, 0}, - {-k_hcp, 0, k_hcp}, - {0, -k_hcp, k_hcp}, - }; - -//ico -#define k_ico 0.13143277802974323576 -#define phi 1.61803398874989490253 -//((1.0 + sqrt(5)) / 2) -const double penrose_ico[PTM_NUM_POINTS_ICO][3] = { - {0, 0, 0}, - {0, k_ico, phi*k_ico}, - {0, -k_ico, -phi*k_ico}, - {0, k_ico, -phi*k_ico}, - {0, -k_ico, phi*k_ico}, - {-k_ico, -phi*k_ico, -0}, - {k_ico, phi*k_ico, 0}, - {k_ico, -phi*k_ico, 0}, - {-k_ico, phi*k_ico, -0}, - {-phi*k_ico, 0, -k_ico}, - {phi*k_ico, 0, k_ico}, - {phi*k_ico, 0, -k_ico}, - {-phi*k_ico, 0, k_ico}, - }; - -//bcc -#define k_bcc 0.11543038598460284017 -const double penrose_bcc[PTM_NUM_POINTS_BCC][3] = { - {0, 0, 0}, - {-k_bcc, -k_bcc, -k_bcc}, - {k_bcc, k_bcc, k_bcc}, - {k_bcc, -k_bcc, -k_bcc}, - {-k_bcc, k_bcc, k_bcc}, - {-k_bcc, k_bcc, -k_bcc}, - {k_bcc, -k_bcc, k_bcc}, - {-k_bcc, -k_bcc, k_bcc}, - {k_bcc, k_bcc, -k_bcc}, - {0, 0, -2*k_bcc}, - {0, 0, 2*k_bcc}, - {0, -2*k_bcc, 0}, - {0, 2*k_bcc, 0}, - {-2*k_bcc, 0, 0}, - {2*k_bcc, 0, -0}, - }; - -//dcub -#define kdcub 0.07095369570691034689 -const double penrose_dcub[PTM_NUM_POINTS_DCUB][3] = { - { 0, 0, 0 }, - { -kdcub, kdcub, kdcub }, - { -kdcub, -kdcub, -kdcub }, - { kdcub, -kdcub, kdcub }, - { kdcub, kdcub, -kdcub }, - { -2 * kdcub, 0, 2 * kdcub }, - { -2 * kdcub, 2 * kdcub, 0 }, - { 0, 2 * kdcub, 2 * kdcub }, - { -2 * kdcub, -2 * kdcub, 0 }, - { -2 * kdcub, 0, -2 * kdcub }, - { 0, -2 * kdcub, -2 * kdcub }, - { 0, -2 * kdcub, 2 * kdcub }, - { 2 * kdcub, -2 * kdcub, 0 }, - { 2 * kdcub, 0, 2 * kdcub }, - { 0, 2 * kdcub, -2 * kdcub }, - { 2 * kdcub, 0, -2 * kdcub }, - { 2 * kdcub, 2 * kdcub, 0 }, - }; - - -#define kdhex 0.04730246380471011397 -const double penrose_dhex[PTM_NUM_POINTS_DHEX][3] = { - { 0, 0, 0 }, - { -kdcub, -kdcub, -kdcub }, - { kdcub, -kdcub, kdcub }, - { -kdcub, kdcub, kdcub }, - { kdcub, kdcub, -kdcub }, - { -kdhex, -4 * kdhex, -kdhex }, - { -4 * kdhex, -kdhex, -kdhex }, - { -kdhex, -kdhex, -4 * kdhex }, - { 2 * kdcub, 0, 2 * kdcub }, - { 2 * kdcub, -2 * kdcub, 0 }, - { 0, -2 * kdcub, 2 * kdcub }, - { 0, 2 * kdcub, 2 * kdcub }, - { -2 * kdcub, 2 * kdcub, 0 }, - { -2 * kdcub, 0, 2 * kdcub }, - { 2 * kdcub, 2 * kdcub, 0 }, - { 0, 2 * kdcub, -2 * kdcub }, - { 2 * kdcub, 0, -2 * kdcub }, - }; -#endif - - diff --git a/src/USER-PTM/fundamental_mappings.h b/src/USER-PTM/fundamental_mappings.h deleted file mode 100644 index 9030d3a2b2..0000000000 --- a/src/USER-PTM/fundamental_mappings.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef FUNDAMENTAL_MAPPINGS_H -#define FUNDAMENTAL_MAPPINGS_H - -#include - -#define NUM_CUBIC_MAPPINGS 24 -#define NUM_ICO_MAPPINGS 60 -#define NUM_HEX_MAPPINGS 6 -#define NUM_DCUB_MAPPINGS 12 -#define NUM_DHEX_MAPPINGS 3 - -const int8_t mapping_sc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { - {0, 1, 2, 3, 4, 5, 6}, - {0, 2, 1, 4, 3, 5, 6}, - {0, 2, 1, 3, 4, 6, 5}, - {0, 1, 2, 4, 3, 6, 5}, - {0, 3, 4, 5, 6, 1, 2}, - {0, 5, 6, 2, 1, 4, 3}, - {0, 6, 5, 1, 2, 4, 3}, - {0, 4, 3, 5, 6, 2, 1}, - {0, 5, 6, 1, 2, 3, 4}, - {0, 4, 3, 6, 5, 1, 2}, - {0, 3, 4, 6, 5, 2, 1}, - {0, 6, 5, 2, 1, 3, 4}, - {0, 3, 4, 2, 1, 5, 6}, - {0, 6, 5, 3, 4, 1, 2}, - {0, 1, 2, 5, 6, 4, 3}, - {0, 4, 3, 1, 2, 5, 6}, - {0, 5, 6, 3, 4, 2, 1}, - {0, 1, 2, 6, 5, 3, 4}, - {0, 2, 1, 5, 6, 3, 4}, - {0, 5, 6, 4, 3, 1, 2}, - {0, 3, 4, 1, 2, 6, 5}, - {0, 2, 1, 6, 5, 4, 3}, - {0, 6, 5, 4, 3, 2, 1}, - {0, 4, 3, 2, 1, 6, 5} }; - -const int8_t mapping_fcc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, - {0, 2, 1, 4, 3, 7, 8, 5, 6, 11, 12, 9, 10}, - {0, 3, 4, 1, 2, 6, 5, 8, 7, 12, 11, 10, 9}, - {0, 4, 3, 2, 1, 8, 7, 6, 5, 10, 9, 12, 11}, - {0, 9, 10, 11, 12, 1, 2, 4, 3, 5, 6, 8, 7}, - {0, 7, 8, 6, 5, 11, 12, 10, 9, 2, 1, 4, 3}, - {0, 8, 7, 5, 6, 10, 9, 11, 12, 4, 3, 2, 1}, - {0, 11, 12, 9, 10, 2, 1, 3, 4, 7, 8, 6, 5}, - {0, 5, 6, 8, 7, 9, 10, 12, 11, 1, 2, 3, 4}, - {0, 10, 9, 12, 11, 4, 3, 1, 2, 8, 7, 5, 6}, - {0, 12, 11, 10, 9, 3, 4, 2, 1, 6, 5, 7, 8}, - {0, 6, 5, 7, 8, 12, 11, 9, 10, 3, 4, 1, 2}, - {0, 3, 4, 2, 1, 9, 10, 11, 12, 7, 8, 5, 6}, - {0, 12, 11, 9, 10, 8, 7, 5, 6, 1, 2, 4, 3}, - {0, 5, 6, 7, 8, 4, 3, 2, 1, 11, 12, 10, 9}, - {0, 4, 3, 1, 2, 11, 12, 9, 10, 5, 6, 7, 8}, - {0, 9, 10, 12, 11, 7, 8, 6, 5, 3, 4, 2, 1}, - {0, 8, 7, 6, 5, 1, 2, 3, 4, 12, 11, 9, 10}, - {0, 7, 8, 5, 6, 3, 4, 1, 2, 9, 10, 12, 11}, - {0, 11, 12, 10, 9, 5, 6, 8, 7, 4, 3, 1, 2}, - {0, 1, 2, 4, 3, 12, 11, 10, 9, 8, 7, 6, 5}, - {0, 6, 5, 8, 7, 2, 1, 4, 3, 10, 9, 11, 12}, - {0, 10, 9, 11, 12, 6, 5, 7, 8, 2, 1, 3, 4}, - {0, 2, 1, 3, 4, 10, 9, 12, 11, 6, 5, 8, 7} }; - -const int8_t mapping_bcc[NUM_CUBIC_MAPPINGS][PTM_MAX_POINTS] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, - {0, 4, 3, 2, 1, 7, 8, 5, 6, 10, 9, 12, 11, 13, 14}, - {0, 6, 5, 7, 8, 2, 1, 3, 4, 10, 9, 11, 12, 14, 13}, - {0, 8, 7, 5, 6, 3, 4, 2, 1, 9, 10, 12, 11, 14, 13}, - {0, 1, 2, 7, 8, 3, 4, 5, 6, 11, 12, 13, 14, 9, 10}, - {0, 4, 3, 7, 8, 5, 6, 2, 1, 13, 14, 10, 9, 12, 11}, - {0, 8, 7, 3, 4, 2, 1, 5, 6, 14, 13, 9, 10, 12, 11}, - {0, 4, 3, 5, 6, 2, 1, 7, 8, 12, 11, 13, 14, 10, 9}, - {0, 1, 2, 5, 6, 7, 8, 3, 4, 13, 14, 9, 10, 11, 12}, - {0, 8, 7, 2, 1, 5, 6, 3, 4, 12, 11, 14, 13, 9, 10}, - {0, 6, 5, 3, 4, 7, 8, 2, 1, 11, 12, 14, 13, 10, 9}, - {0, 6, 5, 2, 1, 3, 4, 7, 8, 14, 13, 10, 9, 11, 12}, - {0, 7, 8, 6, 5, 1, 2, 4, 3, 11, 12, 10, 9, 13, 14}, - {0, 3, 4, 6, 5, 8, 7, 1, 2, 14, 13, 11, 12, 9, 10}, - {0, 5, 6, 1, 2, 8, 7, 4, 3, 9, 10, 13, 14, 12, 11}, - {0, 5, 6, 8, 7, 4, 3, 1, 2, 12, 11, 9, 10, 13, 14}, - {0, 7, 8, 1, 2, 4, 3, 6, 5, 13, 14, 11, 12, 10, 9}, - {0, 3, 4, 8, 7, 1, 2, 6, 5, 9, 10, 14, 13, 11, 12}, - {0, 7, 8, 4, 3, 6, 5, 1, 2, 10, 9, 13, 14, 11, 12}, - {0, 5, 6, 4, 3, 1, 2, 8, 7, 13, 14, 12, 11, 9, 10}, - {0, 3, 4, 1, 2, 6, 5, 8, 7, 11, 12, 9, 10, 14, 13}, - {0, 2, 1, 6, 5, 4, 3, 8, 7, 10, 9, 14, 13, 12, 11}, - {0, 2, 1, 8, 7, 6, 5, 4, 3, 14, 13, 12, 11, 10, 9}, - {0, 2, 1, 4, 3, 8, 7, 6, 5, 12, 11, 10, 9, 14, 13} }; - -const int8_t mapping_ico[NUM_ICO_MAPPINGS][PTM_MAX_POINTS] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, - {0, 10, 9, 8, 7, 5, 6, 2, 1, 12, 11, 3, 4}, - {0, 1, 2, 9, 10, 7, 8, 11, 12, 5, 6, 3, 4}, - {0, 4, 3, 8, 7, 2, 1, 11, 12, 9, 10, 6, 5}, - {0, 6, 5, 9, 10, 4, 3, 7, 8, 12, 11, 2, 1}, - {0, 12, 11, 3, 4, 7, 8, 10, 9, 2, 1, 6, 5}, - {0, 4, 3, 6, 5, 9, 10, 2, 1, 8, 7, 11, 12}, - {0, 8, 7, 2, 1, 4, 3, 10, 9, 5, 6, 11, 12}, - {0, 10, 9, 3, 4, 12, 11, 5, 6, 8, 7, 2, 1}, - {0, 12, 11, 6, 5, 2, 1, 7, 8, 3, 4, 10, 9}, - {0, 1, 2, 11, 12, 9, 10, 5, 6, 3, 4, 7, 8}, - {0, 8, 7, 11, 12, 5, 6, 4, 3, 2, 1, 10, 9}, - {0, 6, 5, 2, 1, 12, 11, 4, 3, 9, 10, 7, 8}, - {0, 3, 4, 5, 6, 1, 2, 10, 9, 12, 11, 7, 8}, - {0, 3, 4, 7, 8, 12, 11, 1, 2, 5, 6, 10, 9}, - {0, 6, 5, 7, 8, 9, 10, 12, 11, 2, 1, 4, 3}, - {0, 9, 10, 11, 12, 4, 3, 1, 2, 7, 8, 6, 5}, - {0, 11, 12, 9, 10, 1, 2, 4, 3, 8, 7, 5, 6}, - {0, 8, 7, 5, 6, 10, 9, 11, 12, 4, 3, 2, 1}, - {0, 10, 9, 2, 1, 8, 7, 12, 11, 3, 4, 5, 6}, - {0, 12, 11, 2, 1, 10, 9, 6, 5, 7, 8, 3, 4}, - {0, 9, 10, 6, 5, 7, 8, 4, 3, 11, 12, 1, 2}, - {0, 8, 7, 10, 9, 2, 1, 5, 6, 11, 12, 4, 3}, - {0, 6, 5, 12, 11, 7, 8, 2, 1, 4, 3, 9, 10}, - {0, 11, 12, 8, 7, 4, 3, 5, 6, 1, 2, 9, 10}, - {0, 4, 3, 11, 12, 8, 7, 9, 10, 6, 5, 2, 1}, - {0, 4, 3, 9, 10, 11, 12, 6, 5, 2, 1, 8, 7}, - {0, 12, 11, 10, 9, 3, 4, 2, 1, 6, 5, 7, 8}, - {0, 5, 6, 8, 7, 11, 12, 10, 9, 3, 4, 1, 2}, - {0, 7, 8, 6, 5, 12, 11, 9, 10, 1, 2, 3, 4}, - {0, 10, 9, 12, 11, 2, 1, 3, 4, 5, 6, 8, 7}, - {0, 7, 8, 1, 2, 9, 10, 3, 4, 12, 11, 6, 5}, - {0, 5, 6, 1, 2, 3, 4, 11, 12, 8, 7, 10, 9}, - {0, 7, 8, 12, 11, 3, 4, 6, 5, 9, 10, 1, 2}, - {0, 1, 2, 5, 6, 11, 12, 3, 4, 7, 8, 9, 10}, - {0, 11, 12, 1, 2, 5, 6, 9, 10, 4, 3, 8, 7}, - {0, 5, 6, 3, 4, 10, 9, 1, 2, 11, 12, 8, 7}, - {0, 5, 6, 10, 9, 8, 7, 3, 4, 1, 2, 11, 12}, - {0, 3, 4, 12, 11, 10, 9, 7, 8, 1, 2, 5, 6}, - {0, 9, 10, 7, 8, 1, 2, 6, 5, 4, 3, 11, 12}, - {0, 9, 10, 1, 2, 11, 12, 7, 8, 6, 5, 4, 3}, - {0, 7, 8, 3, 4, 1, 2, 12, 11, 6, 5, 9, 10}, - {0, 11, 12, 5, 6, 8, 7, 1, 2, 9, 10, 4, 3}, - {0, 1, 2, 7, 8, 3, 4, 9, 10, 11, 12, 5, 6}, - {0, 3, 4, 10, 9, 5, 6, 12, 11, 7, 8, 1, 2}, - {0, 2, 1, 4, 3, 8, 7, 6, 5, 12, 11, 10, 9}, - {0, 2, 1, 12, 11, 6, 5, 10, 9, 8, 7, 4, 3}, - {0, 9, 10, 4, 3, 6, 5, 11, 12, 1, 2, 7, 8}, - {0, 11, 12, 4, 3, 9, 10, 8, 7, 5, 6, 1, 2}, - {0, 2, 1, 10, 9, 12, 11, 8, 7, 4, 3, 6, 5}, - {0, 5, 6, 11, 12, 1, 2, 8, 7, 10, 9, 3, 4}, - {0, 10, 9, 5, 6, 3, 4, 8, 7, 2, 1, 12, 11}, - {0, 12, 11, 7, 8, 6, 5, 3, 4, 10, 9, 2, 1}, - {0, 7, 8, 9, 10, 6, 5, 1, 2, 3, 4, 12, 11}, - {0, 2, 1, 8, 7, 10, 9, 4, 3, 6, 5, 12, 11}, - {0, 8, 7, 4, 3, 11, 12, 2, 1, 10, 9, 5, 6}, - {0, 6, 5, 4, 3, 2, 1, 9, 10, 7, 8, 12, 11}, - {0, 2, 1, 6, 5, 4, 3, 12, 11, 10, 9, 8, 7}, - {0, 3, 4, 1, 2, 7, 8, 5, 6, 10, 9, 12, 11}, - {0, 4, 3, 2, 1, 6, 5, 8, 7, 11, 12, 9, 10} }; - -const int8_t mapping_hcp[NUM_HEX_MAPPINGS][PTM_MAX_POINTS] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, - {0, 5, 6, 1, 2, 3, 4, 9, 10, 12, 11, 8, 7}, - {0, 3, 4, 5, 6, 1, 2, 12, 11, 7, 8, 10, 9}, - {0, 4, 3, 2, 1, 6, 5, 11, 12, 10, 9, 7, 8}, - {0, 2, 1, 6, 5, 4, 3, 8, 7, 11, 12, 9, 10}, - {0, 6, 5, 4, 3, 2, 1, 10, 9, 8, 7, 12, 11} }; - -const int8_t mapping_dcub[NUM_DCUB_MAPPINGS][PTM_MAX_POINTS] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - {0, 2, 1, 4, 3, 9, 8, 10, 6, 5, 7, 14, 16, 15, 11, 13, 12}, - {0, 4, 3, 2, 1, 15, 16, 14, 12, 13, 11, 10, 8, 9, 7, 5, 6}, - {0, 3, 4, 1, 2, 13, 12, 11, 16, 15, 14, 7, 6, 5, 10, 9, 8}, - {0, 4, 2, 1, 3, 14, 15, 16, 9, 10, 8, 6, 5, 7, 12, 11, 13}, - {0, 4, 1, 3, 2, 16, 14, 15, 7, 6, 5, 13, 11, 12, 9, 8, 10}, - {0, 1, 4, 2, 3, 6, 7, 5, 14, 16, 15, 9, 10, 8, 13, 12, 11}, - {0, 3, 1, 2, 4, 11, 13, 12, 5, 7, 6, 8, 9, 10, 16, 14, 15}, - {0, 3, 2, 4, 1, 12, 11, 13, 10, 8, 9, 15, 14, 16, 5, 6, 7}, - {0, 2, 4, 3, 1, 10, 9, 8, 15, 14, 16, 12, 13, 11, 6, 7, 5}, - {0, 1, 3, 4, 2, 7, 5, 6, 13, 11, 12, 16, 15, 14, 8, 10, 9}, - {0, 2, 3, 1, 4, 8, 10, 9, 11, 12, 13, 5, 7, 6, 15, 16, 14} }; - -const int8_t mapping_dhex[NUM_DHEX_MAPPINGS][PTM_MAX_POINTS] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - {0, 1, 3, 4, 2, 6, 7, 5, 11, 13, 12, 14, 16, 15, 8, 9, 10}, - {0, 1, 4, 2, 3, 7, 5, 6, 14, 15, 16, 8, 10, 9, 11, 13, 12} }; - -#endif - diff --git a/src/USER-PTM/graph_data.cpp b/src/USER-PTM/graph_data.cpp deleted file mode 100644 index aea2e59eac..0000000000 --- a/src/USER-PTM/graph_data.cpp +++ /dev/null @@ -1,2059 +0,0 @@ -#include "graph_data.h" - - -int8_t automorphisms[65][17] = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, - { 0, 4, 3, 10, 9, 5, 6, 12, 11, 8, 7, 1, 2, -1, -1, -1, -1}, - { 0, 5, 6, 11, 12, 8, 7, 2, 1, 4, 3, 10, 9, -1, -1, -1, -1}, - { 0, 8, 7, 1, 2, 4, 3, 9, 10, 5, 6, 11, 12, -1, -1, -1, -1}, - { 0, 8, 7, 10, 9, 1, 2, 6, 5, 12, 11, 3, 4, -1, -1, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, - { 0, 12, 3, 2, 7, 10, 8, 4, 6, 11, 5, 9, 1, -1, -1, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, - { 0, 4, 11, 8, 1, 9, 12, 10, 3, 5, 7, 2, 6, -1, -1, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, - { 0, 2, 1, 6, 5, 4, 3, 9, 8, 7, 11, 10, 12, -1, -1, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, - { 0, 1, 7, 10, 11, 9, 6, 4, 2, 12, 5, 8, 3, -1, -1, -1, -1}, - { 0, 1, 11, 9, 2, 3, 6, 8, 4, 10, 12, 7, 5, -1, -1, -1, -1}, - { 0, 3, 6, 1, 11, 9, 2, 10, 12, 5, 7, 4, 8, -1, -1, -1, -1}, - { 0, 3, 11, 9, 12, 8, 2, 4, 10, 1, 5, 6, 7, -1, -1, -1, -1}, - { 0, 8, 2, 3, 11, 9, 12, 1, 5, 7, 6, 10, 4, -1, -1, -1, -1}, - { 0, 9, 2, 3, 6, 1, 11, 5, 7, 8, 4, 12, 10, -1, -1, -1, -1}, - { 0, 9, 6, 1, 7, 10, 11, 12, 5, 3, 8, 2, 4, -1, -1, -1, -1}, - { 0, 9, 12, 8, 2, 3, 11, 7, 6, 4, 10, 5, 1, -1, -1, -1, -1}, - { 0, 10, 11, 9, 6, 1, 7, 3, 8, 4, 2, 5, 12, -1, -1, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, - { 0, 3, 2, 8, 6, 5, 12, 11, 7, 4, 9, 1, 10, -1, -1, -1, -1}, - { 0, 3, 11, 10, 6, 9, 7, 4, 2, 12, 1, 8, 5, -1, -1, -1, -1}, - { 0, 3, 12, 9, 6, 8, 11, 7, 4, 2, 10, 5, 1, -1, -1, -1, -1}, - { 0, 5, 12, 3, 2, 8, 6, 4, 9, 10, 1, 7, 11, -1, -1, -1, -1}, - { 0, 8, 6, 5, 12, 3, 2, 10, 1, 11, 7, 9, 4, -1, -1, -1, -1}, - { 0, 8, 11, 3, 12, 9, 6, 2, 10, 1, 5, 4, 7, -1, -1, -1, -1}, - { 0, 9, 6, 8, 11, 3, 12, 1, 5, 7, 4, 10, 2, -1, -1, -1, -1}, - { 0, 9, 7, 3, 11, 10, 6, 12, 1, 5, 8, 2, 4, -1, -1, -1, -1}, - { 0, 10, 6, 9, 7, 3, 11, 5, 8, 4, 2, 1, 12, -1, -1, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 3, 4, 6, 5, 2, 1, 9, 10, 14, 13, 11, 12, 8, 7, -1, -1}, - { 0, 4, 3, 1, 2, 5, 6, 10, 9, 13, 14, 7, 8, 12, 11, -1, -1}, - { 0, 6, 5, 1, 2, 4, 3, 14, 13, 7, 8, 11, 12, 10, 9, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 12, 11, 10, 9, 13, 14, 8, 7, 4, 3, 2, 1, 5, 6, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 9, 10, 13, 14, 11, 12, 8, 7, 1, 2, 5, 6, 3, 4, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 6, 5, 4, 3, 2, 1, 11, 12, 10, 9, 7, 8, 14, 13, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 12, 11, 10, 9, 13, 14, 8, 7, 4, 3, 2, 1, 5, 6, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 9, 10, 13, 14, 11, 12, 8, 7, 1, 2, 5, 6, 3, 4, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 3, 10, 14, 5, 9, 7, 13, 2, 8, 4, 11, 12, 1, 6, -1, -1}, - { 0, 13, 8, 1, 10, 4, 14, 6, 9, 5, 2, 11, 12, 7, 3, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 11, 12, 14, 13, 9, 10, 7, 8, 3, 4, 6, 5, 1, 2, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, -1}, - { 0, 13, 14, 11, 12, 5, 6, 10, 9, 1, 2, 7, 8, 4, 3, -1, -1}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - { 0, 4, 3, 2, 1, 15, 14, 16, 13, 12, 11, 10, 9, 8, 6, 5, 7}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - { 0, 4, 1, 3, 2, 15, 14, 16, 5, 7, 6, 13, 11, 12, 10, 8, 9}, - { 0, 4, 2, 1, 3, 16, 15, 14, 10, 8, 9, 5, 6, 7, 13, 12, 11}, - { 0, 4, 3, 2, 1, 14, 16, 15, 13, 12, 11, 10, 9, 8, 5, 7, 6}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - { 0, 3, 4, 1, 2, 12, 13, 11, 16, 14, 15, 7, 5, 6, 9, 10, 8}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - { 0, 4, 1, 3, 2, 16, 15, 14, 6, 5, 7, 13, 11, 12, 10, 8, 9}, - { 0, 4, 2, 1, 3, 14, 16, 15, 10, 8, 9, 6, 7, 5, 13, 12, 11}, - { 0, 4, 3, 2, 1, 15, 14, 16, 13, 12, 11, 10, 9, 8, 6, 5, 7}, -}; - -graph_t graphs_sc[NUM_SC_GRAPHS] = { - -{0, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,4},{1,3,5},{0,3,4},{0,3,5},{1,2,5},{1,2,4},{0,2,4},{0,2,5}}}, - -}; - -graph_t graphs_ico[NUM_ICO_GRAPHS] = { - -{0, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,5,9},{1,2,8},{0,5,7},{2,7,8},{2,5,7},{1,4,8},{1,2,10},{5,9,10},{2,5,10},{4,8,11},{7,8,11},{0,7,11},{0,3,9},{0,3,11},{3,4,11},{3,6,9},{3,4,6},{6,9,10},{1,4,6},{1,6,10}}}, - -}; - -graph_t graphs_fcc[NUM_FCC_GRAPHS] = { - -{0, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{1,3,10},{1,3,9},{4,6,10},{4,6,8}}}, - -{1, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, - -{2, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{1,2,6},{1,2,5},{3,9,10},{1,9,10},{6,8,10},{4,8,10}}}, - -{3, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{4,6,10},{4,6,8}}}, - -{4, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, - -{5, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{5,7,11},{5,7,9},{2,5,6},{1,5,6},{3,9,10},{1,9,10},{4,6,10},{4,6,8}}}, - -{6, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{7,9,11},{5,9,11},{1,2,6},{1,2,5},{3,9,10},{1,9,10},{4,6,10},{4,6,8}}}, - -{7, -0, -1, -5, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{0,4,8},{3,7,9},{2,5,11},{0,7,11},{1,5,9},{2,6,8},{3,4,10},{1,6,10},{3,4,7},{0,4,7},{0,2,11},{0,2,8},{7,9,11},{5,9,11},{2,5,6},{1,5,6},{1,3,10},{1,3,9},{6,8,10},{4,8,10}}}, - -}; - -graph_t graphs_hcp[NUM_HCP_GRAPHS] = { - -{0, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, - -{1, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, - -{2, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, - -{3, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, - -{4, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, - -{5, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, - -{6, -0, -6, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, - -{7, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, - -{8, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{2,6,7},{2,4,6}}}, - -{9, -0, -8, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, - -{10, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{4,10,11},{0,4,11},{4,6,7},{2,4,7}}}, - -{11, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{0,8,9},{0,2,8},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, - -{12, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, - -{13, -0, -10, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{5,6,7},{3,5,7},{3,8,9},{1,3,9},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, - -{14, -0, -12, -10, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{1,10,11},{1,5,10},{5,6,7},{3,5,7},{3,8,9},{1,3,9},{0,8,9},{0,2,8},{4,10,11},{0,4,11},{2,6,7},{2,4,6}}}, - -{15, -0, -22, -10, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,5},{5,6,10},{0,9,11},{1,9,11},{3,7,8},{2,7,8},{4,6,10},{0,2,4},{5,10,11},{1,5,11},{3,6,7},{3,5,6},{1,8,9},{1,3,8},{2,8,9},{0,2,9},{0,10,11},{0,4,10},{4,6,7},{2,4,7}}}, - -}; - -graph_t graphs_bcc[NUM_BCC_GRAPHS] = { - -{0, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{1, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{2, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{3, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{4, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{5, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{6, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{7, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{8, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{9, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{10, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{11, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{12, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{13, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{14, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{15, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{16, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{17, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{18, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{19, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{20, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{21, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{22, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{23, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{24, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{25, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{26, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{27, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{28, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{29, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{30, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{31, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{32, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{33, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{34, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{35, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{36, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{37, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{38, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{39, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{40, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{41, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{42, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{43, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{44, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{45, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{46, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{47, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{48, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{49, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{50, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{51, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{52, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{53, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{54, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{55, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{56, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{57, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{58, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{59, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{60, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{61, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{62, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{63, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{64, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{65, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{66, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{67, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{68, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{69, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{70, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{71, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{72, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{73, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{74, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{75, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{76, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{77, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{78, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{79, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{80, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{81, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{82, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{83, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{84, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{85, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{86, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{87, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{88, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{89, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{90, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{91, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{92, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{93, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{94, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{95, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{96, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{97, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{98, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{99, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{100, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{101, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{102, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{103, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{104, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{105, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{106, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{107, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{108, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{109, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{110, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{111, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{112, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{113, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{114, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{115, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{116, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{117, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{118, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{119, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{120, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{121, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{122, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{123, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{124, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{125, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{126, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{127, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{128, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{129, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{130, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{131, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{132, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{133, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{134, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{135, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{136, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{137, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{138, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{139, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{140, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{141, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{142, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{143, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{144, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{145, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{146, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{147, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{148, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{149, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{150, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{151, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{152, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{153, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{154, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{155, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{156, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{157, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{158, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{159, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{160, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{161, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{162, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{163, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{164, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{165, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{7,11,13},{1,11,13},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{166, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{167, -0, -32, -4, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{168, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{169, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{170, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{171, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{172, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{173, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{174, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{175, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{176, -0, -36, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{5,9,13},{1,9,13},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{177, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{178, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{179, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{180, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{6,9,12},{3,9,12},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{181, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{182, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{183, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{184, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{185, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{186, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{187, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{188, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{189, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{190, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{191, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{192, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{193, -0, -38, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{194, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{195, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{196, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{197, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{198, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{199, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{200, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{201, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{202, -0, -40, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{2,8,10},{0,8,10}}}, - -{203, -0, -42, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{204, -0, -44, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{205, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{4,11,12},{3,11,12},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{206, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{207, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{6,9,10},{5,9,10},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{208, -0, -46, -3, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{209, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{210, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{7,8,11},{4,8,11},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{211, -0, -49, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{5,10,13},{2,10,13},{0,2,10},{0,2,8}}}, - -{212, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{4,8,12},{0,8,12},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{213, -0, -51, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{7,8,13},{2,8,13},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{214, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{6,10,12},{0,10,12},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{215, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{2,8,10},{0,8,10}}}, - -{216, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{3,9,11},{1,9,11},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -{217, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{1,3,11},{1,3,9},{3,4,12},{3,4,11},{1,7,13},{1,7,11},{4,7,11},{4,7,8},{1,5,13},{1,5,9},{3,6,12},{3,6,9},{5,6,10},{5,6,9},{0,4,12},{0,4,8},{0,6,12},{0,6,10},{2,7,13},{2,7,8},{2,5,13},{2,5,10},{0,2,10},{0,2,8}}}, - -}; - -graph_t graphs_dcub[NUM_DCUB_GRAPHS] = { - -{0, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, - -{1, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{12,14,15},{11,12,14}}}, - -{2, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, - -{3, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, - -{4, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, - -{5, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, - -{6, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, - -{7, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{5,13,15},{5,6,15},{8,13,14},{8,9,14},{12,14,15},{11,12,14}}}, - -{8, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{9,13,14},{8,9,13},{11,14,15},{11,12,15}}}, - -{9, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{6,10,12},{4,6,10},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, - -{10, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{5,7,8},{4,5,7},{4,10,12},{4,6,12},{9,10,11},{7,9,10},{6,13,15},{5,6,13},{8,13,14},{8,9,14},{11,14,15},{11,12,15}}}, - -{11, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{4,7,10},{0,5,6},{0,4,5},{0,4,6},{2,11,12},{2,10,12},{2,10,11},{1,7,8},{1,8,9},{1,7,9},{6,12,15},{5,8,13},{3,13,15},{3,13,14},{9,11,14},{3,14,15},{4,7,8},{4,5,8},{6,10,12},{4,6,10},{7,10,11},{7,9,11},{5,13,15},{5,6,15},{9,13,14},{8,9,13},{12,14,15},{11,12,14}}}, - -}; - -graph_t graphs_dhex[NUM_DHEX_GRAPHS] = { - -{0, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{7,13,15},{7,8,15}}}, - -{1, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{2, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, - -{3, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{4, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{5, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, - -{6, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{7, -0, -53, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{8, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, - -{9, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{10, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{11, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, - -{12, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{13, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{14, -0, -55, -4, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{7,13,15},{7,8,15}}}, - -{15, -0, -59, -2, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{11,13,14},{10,11,13},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{16, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{17, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{18, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{19, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{9,10,12},{7,9,10},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{20, -0, -61, -4, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{4,8,15},{4,6,15},{8,13,15},{7,8,13}}}, - -{21, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{6,11,14},{5,6,11},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{22, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{5,9,12},{4,5,9},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -{23, -0, -0, -1, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{{7,10,13},{5,11,12},{6,14,15},{0,4,5},{0,5,6},{0,4,6},{4,8,9},{2,10,12},{2,10,11},{2,11,12},{3,13,14},{3,13,15},{3,14,15},{1,7,9},{1,7,8},{1,8,9},{7,10,12},{7,9,12},{4,9,12},{4,5,12},{10,13,14},{10,11,14},{5,11,14},{5,6,14},{6,8,15},{4,6,8},{8,13,15},{7,8,13}}}, - -}; - diff --git a/src/USER-PTM/graph_data.h b/src/USER-PTM/graph_data.h deleted file mode 100644 index 3a8a5c7ae7..0000000000 --- a/src/USER-PTM/graph_data.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef GRAPH_DATA_H -#define GRAPH_DATA_H - -#include -#include "ptm_constants.h" - - -typedef struct -{ - int id; - uint64_t hash; - int automorphism_index; - int num_automorphisms; - int8_t canonical_labelling[PTM_MAX_POINTS]; - int8_t facets[PTM_MAX_FACETS][3]; -} graph_t; - -#define NUM_SC_GRAPHS 1 -#define NUM_ICO_GRAPHS 1 -#define NUM_FCC_GRAPHS 8 -#define NUM_HCP_GRAPHS 16 -#define NUM_BCC_GRAPHS 218 -#define NUM_DCUB_GRAPHS 12 -#define NUM_DHEX_GRAPHS 24 - -extern int8_t automorphisms[][PTM_MAX_POINTS]; - -extern graph_t graphs_sc[NUM_SC_GRAPHS]; -extern graph_t graphs_fcc[NUM_FCC_GRAPHS]; -extern graph_t graphs_hcp[NUM_HCP_GRAPHS]; -extern graph_t graphs_ico[NUM_ICO_GRAPHS]; -extern graph_t graphs_bcc[NUM_BCC_GRAPHS]; -extern graph_t graphs_dcub[NUM_DCUB_GRAPHS]; -extern graph_t graphs_dhex[NUM_DHEX_GRAPHS]; - -#endif - diff --git a/src/USER-PTM/graph_tools.cpp b/src/USER-PTM/graph_tools.cpp deleted file mode 100644 index 864e921b51..0000000000 --- a/src/USER-PTM/graph_tools.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include "graph_tools.h" -#include "ptm_constants.h" - - -bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]) -{ - memset(common, -1, sizeof(int8_t) * PTM_MAX_NBRS * PTM_MAX_NBRS); - - for (int i = 0;i -#include "ptm_constants.h" - -bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]); -int graph_degree(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree); - -#endif - diff --git a/src/USER-PTM/index_ptm.cpp b/src/USER-PTM/index_ptm.cpp deleted file mode 100644 index 2683323ac5..0000000000 --- a/src/USER-PTM/index_ptm.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "convex_hull_incremental.h" -#include "graph_data.h" -#include "deformation_gradient.h" -#include "alloy_types.h" -#include "neighbour_ordering.h" -#include "normalize_vertices.h" -#include "quat.h" -#include "polar.h" -#include "initialize_data.h" -#include "structure_matcher.h" -#include "ptm_functions.h" -#include "ptm_constants.h" - - -//todo: verify that c == norm(template[1]) -static double calculate_interatomic_distance(int type, double scale) -{ - assert(type >= 1 && type <= 7); - double c[8] = {0, 1, 1, (7. - 3.5 * sqrt(3)), 1, 1, sqrt(3) * 4. / (6 * sqrt(2) + sqrt(3)), sqrt(3) * 4. / (6 * sqrt(2) + sqrt(3))}; - return c[type] / scale; -} - -static double calculate_lattice_constant(int type, double interatomic_distance) -{ - assert(type >= 1 && type <= 7); - double c[8] = {0, 2 / sqrt(2), 2 / sqrt(2), 2. / sqrt(3), 2 / sqrt(2), 1, 4 / sqrt(3), 4 / sqrt(3)}; - return c[type] * interatomic_distance; -} - -static int rotate_into_fundamental_zone(int type, double* q) -{ - if (type == PTM_MATCH_SC) return rotate_quaternion_into_cubic_fundamental_zone(q); - if (type == PTM_MATCH_FCC) return rotate_quaternion_into_cubic_fundamental_zone(q); - if (type == PTM_MATCH_BCC) return rotate_quaternion_into_cubic_fundamental_zone(q); - if (type == PTM_MATCH_ICO) return rotate_quaternion_into_icosahedral_fundamental_zone(q); - if (type == PTM_MATCH_HCP) return rotate_quaternion_into_hcp_fundamental_zone(q); - if (type == PTM_MATCH_DCUB) return rotate_quaternion_into_diamond_cubic_fundamental_zone(q); - if (type == PTM_MATCH_DHEX) return rotate_quaternion_into_diamond_hexagonal_fundamental_zone(q); - return -1; -} - -static void order_points(ptm_local_handle_t local_handle, int num_points, double (*unpermuted_points)[3], int32_t* unpermuted_numbers, bool topological_ordering, - int8_t* ordering, double (*points)[3], int32_t* numbers) -{ - if (topological_ordering) - { - double normalized_points[PTM_MAX_INPUT_POINTS][3]; - normalize_vertices(num_points, unpermuted_points, normalized_points); - int ret = calculate_neighbour_ordering((void*)local_handle, num_points, (const double (*)[3])normalized_points, ordering); - if (ret != 0) - topological_ordering = false; - } - - if (!topological_ordering) - for (int i=0;iref_struct; - if (ref == NULL) - return; - - *p_type = ref->type; - if (p_alloy_type != NULL && unpermuted_numbers != NULL) - *p_alloy_type = find_alloy_type(ref, res->mapping, numbers); - - int bi = rotate_into_fundamental_zone(ref->type, res->q); - int8_t temp[PTM_MAX_POINTS]; - for (int i=0;inum_nbrs+1;i++) - temp[ref->mapping[bi][i]] = res->mapping[i]; - - memcpy(res->mapping, temp, (ref->num_nbrs+1) * sizeof(int8_t)); - - if (F != NULL && F_res != NULL) - { - double scaled_points[PTM_MAX_INPUT_POINTS][3]; - - subtract_barycentre(ref->num_nbrs + 1, points, scaled_points); - for (int i = 0;inum_nbrs + 1;i++) - { - scaled_points[i][0] *= res->scale; - scaled_points[i][1] *= res->scale; - scaled_points[i][2] *= res->scale; - } - calculate_deformation_gradient(ref->num_nbrs + 1, ref->points, res->mapping, scaled_points, ref->penrose, F, F_res); - - if (P != NULL && U != NULL) - polar_decomposition_3x3(F, false, U, P); - } - - if (mapping != NULL) - for (int i=0;inum_nbrs + 1;i++) - mapping[i] = ordering[res->mapping[i]]; - - double interatomic_distance = calculate_interatomic_distance(ref->type, res->scale); - double lattice_constant = calculate_lattice_constant(ref->type, interatomic_distance); - - if (p_interatomic_distance != NULL) - *p_interatomic_distance = interatomic_distance; - - if (p_lattice_constant != NULL) - *p_lattice_constant = lattice_constant; - - *p_rmsd = res->rmsd; - *p_scale = res->scale; - memcpy(q, res->q, 4 * sizeof(double)); -} - - -extern bool ptm_initialized; - -int ptm_index( ptm_local_handle_t local_handle, int32_t flags, - int num_points, double (*unpermuted_points)[3], int32_t* unpermuted_numbers, bool topological_ordering, - int32_t* p_type, int32_t* p_alloy_type, double* p_scale, double* p_rmsd, double* q, double* F, double* F_res, - double* U, double* P, int8_t* mapping, double* p_interatomic_distance, double* p_lattice_constant) -{ - assert(ptm_initialized); - assert(num_points <= PTM_MAX_INPUT_POINTS); - - if (flags & PTM_CHECK_SC) - assert(num_points >= PTM_NUM_POINTS_SC); - - if (flags & PTM_CHECK_BCC) - assert(num_points >= PTM_NUM_POINTS_BCC); - - if (flags & (PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO)) - assert(num_points >= PTM_NUM_POINTS_FCC); - - if (flags & (PTM_CHECK_DCUB | PTM_CHECK_DHEX)) - assert(num_points >= PTM_NUM_POINTS_DCUB); - - int ret = 0; - result_t res; - res.ref_struct = NULL; - res.rmsd = INFINITY; - - int8_t ordering[PTM_MAX_INPUT_POINTS]; - double points[PTM_MAX_POINTS][3]; - int32_t numbers[PTM_MAX_POINTS]; - - int8_t dordering[PTM_MAX_INPUT_POINTS]; - double dpoints[PTM_MAX_POINTS][3]; - int32_t dnumbers[PTM_MAX_POINTS]; - - convexhull_t ch; - double ch_points[PTM_MAX_INPUT_POINTS][3]; - - if (flags & (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC)) - { - int num_lpoints = std::min(std::min(PTM_MAX_POINTS, 20), num_points); - order_points(local_handle, num_lpoints, unpermuted_points, unpermuted_numbers, topological_ordering, ordering, points, numbers); - normalize_vertices(num_lpoints, points, ch_points); - ch.ok = false; - - if (flags & PTM_CHECK_SC) - ret = match_general(&structure_sc, ch_points, points, &ch, &res); - - if (flags & (PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO)) - ret = match_fcc_hcp_ico(ch_points, points, flags, &ch, &res); - - if (flags & PTM_CHECK_BCC) - ret = match_general(&structure_bcc, ch_points, points, &ch, &res); - } - - if (flags & (PTM_CHECK_DCUB | PTM_CHECK_DHEX)) - { - ret = calculate_diamond_neighbour_ordering(num_points, unpermuted_points, unpermuted_numbers, dordering, dpoints, dnumbers); - if (ret == 0) - { - normalize_vertices(PTM_NUM_NBRS_DCUB + 1, dpoints, ch_points); - ch.ok = false; - - ret = match_dcub_dhex(ch_points, dpoints, flags, &ch, &res); - } - } - - if (res.ref_struct != NULL && (res.ref_struct->type == PTM_MATCH_DCUB || res.ref_struct->type == PTM_MATCH_DHEX)) - { - output_data( &res, num_points, unpermuted_numbers, dpoints, dnumbers, dordering, - p_type, p_alloy_type, p_scale, p_rmsd, q, F, F_res, - U, P, mapping, p_interatomic_distance, p_lattice_constant); - } - else - { - output_data( &res, num_points, unpermuted_numbers, points, numbers, ordering, - p_type, p_alloy_type, p_scale, p_rmsd, q, F, F_res, - U, P, mapping, p_interatomic_distance, p_lattice_constant); - } - - return PTM_NO_ERROR; -} - diff --git a/src/USER-PTM/initialize_data.cpp b/src/USER-PTM/initialize_data.cpp deleted file mode 100644 index 6c177bfb70..0000000000 --- a/src/USER-PTM/initialize_data.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "initialize_data.h" - - -static void make_facets_clockwise(int num_facets, int8_t (*facets)[3], const double (*points)[3]) -{ - double plane_normal[3]; - double origin[3] = {0, 0, 0}; - - for (int i = 0;inum_graphs;i++) - { - int8_t code[2 * PTM_MAX_EDGES]; - int8_t degree[PTM_MAX_NBRS]; - int _max_degree = graph_degree(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree); - assert(_max_degree <= s->max_degree); - - make_facets_clockwise(s->num_facets, s->graphs[i].facets, &s->points[1]); - int ret = canonical_form_coloured(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree, colours, s->graphs[i].canonical_labelling, (int8_t*)&code[0], &s->graphs[i].hash); - if (ret != 0) - return ret; - } - - return PTM_NO_ERROR; -} - -bool ptm_initialized = false; -int ptm_initialize_global() -{ - if (ptm_initialized) - return PTM_NO_ERROR; - - int8_t colours[PTM_MAX_POINTS] = {0}; - int8_t dcolours[PTM_MAX_POINTS] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - int ret = initialize_graphs(&structure_sc, colours); - ret |= initialize_graphs(&structure_fcc, colours); - ret |= initialize_graphs(&structure_hcp, colours); - ret |= initialize_graphs(&structure_ico, colours); - ret |= initialize_graphs(&structure_bcc, colours); - ret |= initialize_graphs(&structure_dcub, dcolours); - ret |= initialize_graphs(&structure_dhex, dcolours); - - if (ret == PTM_NO_ERROR) - ptm_initialized = true; - - return ret; -} - -ptm_local_handle_t ptm_initialize_local() -{ - assert(ptm_initialized); - return (ptm_local_handle_t)voronoi_initialize_local(); -} - -void ptm_uninitialize_local(ptm_local_handle_t ptr) -{ - voronoi_uninitialize_local(ptr); -} - diff --git a/src/USER-PTM/initialize_data.h b/src/USER-PTM/initialize_data.h deleted file mode 100644 index 644dfea8c4..0000000000 --- a/src/USER-PTM/initialize_data.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef INITIALIZE_DATA_H -#define INITIALIZE_DATA_H - - -#include "graph_data.h" -#include "graph_tools.h" -#include "deformation_gradient.h" -#include "fundamental_mappings.h" -#include "neighbour_ordering.h" -#include "canonical_coloured.h" -#include "convex_hull_incremental.h" - - -typedef struct -{ - int type; - int num_nbrs; - int num_facets; - int max_degree; - int num_graphs; - int num_mappings; - graph_t* graphs; - const double (*points)[3]; - const double (*penrose)[3]; - const int8_t (*mapping)[PTM_MAX_POINTS]; -} refdata_t; - - -//refdata_t structure_sc = { .type = PTM_MATCH_SC, .num_nbrs = 6, .num_facets = 8, .max_degree = 4, .num_graphs = NUM_SC_GRAPHS, .graphs = graphs_sc, .points = ptm_template_sc, .penrose = penrose_sc , .mapping = mapping_sc }; -const refdata_t structure_sc = { PTM_MATCH_SC, 6, 8, 4, NUM_SC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_sc, ptm_template_sc, penrose_sc, mapping_sc }; -const refdata_t structure_fcc = { PTM_MATCH_FCC, 12, 20, 6, NUM_FCC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_fcc, ptm_template_fcc, penrose_fcc, mapping_fcc }; -const refdata_t structure_hcp = { PTM_MATCH_HCP, 12, 20, 6, NUM_HCP_GRAPHS, NUM_HEX_MAPPINGS, graphs_hcp, ptm_template_hcp, penrose_hcp, mapping_hcp }; -const refdata_t structure_ico = { PTM_MATCH_ICO, 12, 20, 6, NUM_ICO_GRAPHS, NUM_ICO_MAPPINGS, graphs_ico, ptm_template_ico, penrose_ico, mapping_ico }; -const refdata_t structure_bcc = { PTM_MATCH_BCC, 14, 24, 8, NUM_BCC_GRAPHS, NUM_CUBIC_MAPPINGS, graphs_bcc, ptm_template_bcc, penrose_bcc, mapping_bcc }; -const refdata_t structure_dcub = { PTM_MATCH_DCUB, 16, 28, 8, NUM_DCUB_GRAPHS, NUM_DCUB_MAPPINGS, graphs_dcub, ptm_template_dcub, penrose_dcub, mapping_dcub }; -const refdata_t structure_dhex = { PTM_MATCH_DHEX, 16, 28, 8, NUM_DHEX_GRAPHS, NUM_DHEX_MAPPINGS, graphs_dhex, ptm_template_dhex, penrose_dhex, mapping_dhex }; - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct ptm_local_handle* ptm_local_handle_t; -ptm_local_handle_t ptm_initialize_local(); -void ptm_uninitialize_local(ptm_local_handle_t ptr); - -int ptm_initialize_global(); - -//------------------------------------ -// global initialization switch -//------------------------------------ -extern bool ptm_initialized; - - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/src/USER-PTM/neighbour_ordering.cpp b/src/USER-PTM/neighbour_ordering.cpp deleted file mode 100644 index 8e8b016cfc..0000000000 --- a/src/USER-PTM/neighbour_ordering.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#include -#include -#include -#include -#include -#include "ptm_constants.h" -#include "cell.h" -using namespace voro; - - - -typedef struct -{ - double area; - double dist; - int index; -} sorthelper_t; - -static bool sorthelper_compare(sorthelper_t const& a, sorthelper_t const& b) -{ - if (a.area > b.area) - return true; - - if (a.area < b.area) - return false; - - if (a.dist < b.dist) - return true; - - return false; -} - -//todo: change voronoi code to return errors rather than exiting -static int calculate_voronoi_face_areas(int num_points, const double (*_points)[3], double* normsq, double max_norm, voronoicell_neighbor* v, std::vector& nbr_indices, std::vector& face_areas) -{ - const double k = 1000 * max_norm; //todo: reduce this constant - v->init(-k,k,-k,k,-k,k); - - for (int i=1;inplane(x,y,z,normsq[i],i); - } - - v->neighbors(nbr_indices); - v->face_areas(face_areas); - return 0; -} - -int calculate_neighbour_ordering(void* _voronoi_handle, int num_points, const double (*_points)[3], int8_t* ordering) -{ - assert(num_points <= PTM_MAX_INPUT_POINTS); - - voronoicell_neighbor* voronoi_handle = (voronoicell_neighbor*)_voronoi_handle; - - double max_norm = 0; - double points[PTM_MAX_INPUT_POINTS][3]; - double normsq[PTM_MAX_INPUT_POINTS]; - for (int i = 0;i nbr_indices(num_points + 6); - std::vector face_areas(num_points + 6); - int ret = calculate_voronoi_face_areas(num_points, points, normsq, max_norm, voronoi_handle, nbr_indices, face_areas); - if (ret != 0) - return ret; - - double areas[PTM_MAX_INPUT_POINTS]; - memset(areas, 0, num_points * sizeof(double)); - areas[0] = INFINITY; - for (size_t i=0;i 0) - areas[index] = face_areas[i]; - } - - sorthelper_t data[PTM_MAX_INPUT_POINTS]; - for (int i=0;i= 3) - continue; - - ordering[1 + 4 + 3 * p + counts[p]] = q; - counts[p]++; - index++; - num_found++; - if (num_found >= 12) - break; - } - - if (num_found != 12) - return -1; - - for (int i=0;i - - -void subtract_barycentre(int num, double (*points)[3], double (*normalized)[3]) -{ - //calculate barycentre - double sum[3] = {0, 0, 0}; - for (int i=0;i nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Source: started anew. - * - * Change History: - * 2009/04/13 Started source - * 2010/03/28 Modified FastCalcRMSDAndRotation() to handle tiny qsqr - * If trying all rows of the adjoint still gives too small - * qsqr, then just return identity matrix. (DLT) - * 2010/06/30 Fixed prob in assigning A[9] = 0 in InnerProduct() - * invalid mem access - * 2011/02/21 Made CenterCoords use weights - * 2011/05/02 Finally changed CenterCoords declaration in qcprot.h - * Also changed some functions to static - * 2011/07/08 put in fabs() to fix taking sqrt of small neg numbers, fp error - * 2012/07/26 minor changes to comments and main.c, more info (v.1.4) - * - * 2016/05/29 QCP method adapted for polar decomposition of a 3x3 matrix, - * for use in Polyhedral Template Matching. - * - ******************************************************************************/ - -#include -#include -#include -#include "quat.h" - - -static void matmul_3x3(double* A, double* x, double* b) -{ - b[0] = A[0] * x[0] + A[1] * x[3] + A[2] * x[6]; - b[3] = A[3] * x[0] + A[4] * x[3] + A[5] * x[6]; - b[6] = A[6] * x[0] + A[7] * x[3] + A[8] * x[6]; - - b[1] = A[0] * x[1] + A[1] * x[4] + A[2] * x[7]; - b[4] = A[3] * x[1] + A[4] * x[4] + A[5] * x[7]; - b[7] = A[6] * x[1] + A[7] * x[4] + A[8] * x[7]; - - b[2] = A[0] * x[2] + A[1] * x[5] + A[2] * x[8]; - b[5] = A[3] * x[2] + A[4] * x[5] + A[5] * x[8]; - b[8] = A[6] * x[2] + A[7] * x[5] + A[8] * x[8]; -} - -static double matrix_determinant_3x3(double* A) -{ - return A[0] * (A[4]*A[8] - A[5]*A[7]) - - A[1] * (A[3]*A[8] - A[5]*A[6]) - + A[2] * (A[3]*A[7] - A[4]*A[6]); -} - -static void flip_matrix(double* A) -{ - for (int i=0;i<9;i++) - A[i] = -A[i]; -} - -static bool optimal_quaternion(double* A, bool polar, double E0, double* p_nrmsdsq, double* qopt) -{ - const double evecprec = 1e-6; - const double evalprec = 1e-11; - - double Sxx = A[0], Sxy = A[1], Sxz = A[2], - Syx = A[3], Syy = A[4], Syz = A[5], - Szx = A[6], Szy = A[7], Szz = A[8]; - - double Sxx2 = Sxx * Sxx, Syy2 = Syy * Syy, Szz2 = Szz * Szz, - Sxy2 = Sxy * Sxy, Syz2 = Syz * Syz, Sxz2 = Sxz * Sxz, - Syx2 = Syx * Syx, Szy2 = Szy * Szy, Szx2 = Szx * Szx; - - double fnorm_squared = Sxx2 + Syy2 + Szz2 + Sxy2 + Syz2 + Sxz2 + Syx2 + Szy2 + Szx2; - - double SyzSzymSyySzz2 = 2.0 * (Syz * Szy - Syy * Szz); - double Sxx2Syy2Szz2Syz2Szy2 = Syy2 + Szz2 - Sxx2 + Syz2 + Szy2; - double SxzpSzx = Sxz + Szx; - double SyzpSzy = Syz + Szy; - double SxypSyx = Sxy + Syx; - double SyzmSzy = Syz - Szy; - double SxzmSzx = Sxz - Szx; - double SxymSyx = Sxy - Syx; - double SxxpSyy = Sxx + Syy; - double SxxmSyy = Sxx - Syy; - double Sxy2Sxz2Syx2Szx2 = Sxy2 + Sxz2 - Syx2 - Szx2; - - double C[3]; - C[0] = Sxy2Sxz2Syx2Szx2 * Sxy2Sxz2Syx2Szx2 - + (Sxx2Syy2Szz2Syz2Szy2 + SyzSzymSyySzz2) * (Sxx2Syy2Szz2Syz2Szy2 - SyzSzymSyySzz2) - + (-(SxzpSzx)*(SyzmSzy)+(SxymSyx)*(SxxmSyy-Szz)) * (-(SxzmSzx)*(SyzpSzy)+(SxymSyx)*(SxxmSyy+Szz)) - + (-(SxzpSzx)*(SyzpSzy)-(SxypSyx)*(SxxpSyy-Szz)) * (-(SxzmSzx)*(SyzmSzy)-(SxypSyx)*(SxxpSyy+Szz)) - + (+(SxypSyx)*(SyzpSzy)+(SxzpSzx)*(SxxmSyy+Szz)) * (-(SxymSyx)*(SyzmSzy)+(SxzpSzx)*(SxxpSyy+Szz)) - + (+(SxypSyx)*(SyzmSzy)+(SxzmSzx)*(SxxmSyy-Szz)) * (-(SxymSyx)*(SyzpSzy)+(SxzmSzx)*(SxxpSyy-Szz)); - - C[1] = 8.0 * (Sxx*Syz*Szy + Syy*Szx*Sxz + Szz*Sxy*Syx - Sxx*Syy*Szz - Syz*Szx*Sxy - Szy*Syx*Sxz); - C[2] = -2.0 * fnorm_squared; - - //Newton-Raphson - double mxEigenV = polar ? sqrt(3 * fnorm_squared) : E0; - if (mxEigenV > evalprec) - { - for (int i=0;i<50;i++) - { - double oldg = mxEigenV; - double x2 = mxEigenV*mxEigenV; - double b = (x2 + C[2])*mxEigenV; - double a = b + C[1]; - double delta = ((a * mxEigenV + C[0]) / (2 * x2 * mxEigenV + b + a)); - mxEigenV -= delta; - if (fabs(mxEigenV - oldg) < fabs(evalprec * mxEigenV)) - break; - } - } - else - { - mxEigenV = 0.0; - } - - (*p_nrmsdsq) = std::max(0.0, 2.0 * (E0 - mxEigenV)); - - double a11 = SxxpSyy + Szz - mxEigenV; - double a12 = SyzmSzy; - double a13 = -SxzmSzx; - double a14 = SxymSyx; - - double a21 = SyzmSzy; - double a22 = SxxmSyy - Szz -mxEigenV; - double a23 = SxypSyx; - double a24 = SxzpSzx; - - double a31 = a13; - double a32 = a23; - double a33 = Syy - Sxx - Szz - mxEigenV; - double a34 = SyzpSzy; - - double a41 = a14; - double a42 = a24; - double a43 = a34; - double a44 = Szz - SxxpSyy - mxEigenV; - - double a3344_4334 = a33 * a44 - a43 * a34; - double a3244_4234 = a32 * a44 - a42 * a34; - double a3243_4233 = a32 * a43 - a42 * a33; - double a3143_4133 = a31 * a43 - a41 * a33; - double a3144_4134 = a31 * a44 - a41 * a34; - double a3142_4132 = a31 * a42 - a41 * a32; - double a1324_1423 = a13 * a24 - a14 * a23; - double a1224_1422 = a12 * a24 - a14 * a22; - double a1223_1322 = a12 * a23 - a13 * a22; - double a1124_1421 = a11 * a24 - a14 * a21; - double a1123_1321 = a11 * a23 - a13 * a21; - double a1122_1221 = a11 * a22 - a12 * a21; - - double q[4][4]; - q[0][0] = a12 * a3344_4334 - a13 * a3244_4234 + a14 * a3243_4233; - q[0][1] = -a11 * a3344_4334 + a13 * a3144_4134 - a14 * a3143_4133; - q[0][2] = a11 * a3244_4234 - a12 * a3144_4134 + a14 * a3142_4132; - q[0][3] = -a11 * a3243_4233 + a12 * a3143_4133 - a13 * a3142_4132; - - q[1][0] = a22 * a3344_4334 - a23 * a3244_4234 + a24 * a3243_4233; - q[1][1] = -a21 * a3344_4334 + a23 * a3144_4134 - a24 * a3143_4133; - q[1][2] = a21 * a3244_4234 - a22 * a3144_4134 + a24 * a3142_4132; - q[1][3] = -a21 * a3243_4233 + a22 * a3143_4133 - a23 * a3142_4132; - - q[2][0] = a32 * a1324_1423 - a33 * a1224_1422 + a34 * a1223_1322; - q[2][1] = -a31 * a1324_1423 + a33 * a1124_1421 - a34 * a1123_1321; - q[2][2] = a31 * a1224_1422 - a32 * a1124_1421 + a34 * a1122_1221; - q[2][3] = -a31 * a1223_1322 + a32 * a1123_1321 - a33 * a1122_1221; - - q[3][0] = a42 * a1324_1423 - a43 * a1224_1422 + a44 * a1223_1322; - q[3][1] = -a41 * a1324_1423 + a43 * a1124_1421 - a44 * a1123_1321; - q[3][2] = a41 * a1224_1422 - a42 * a1124_1421 + a44 * a1122_1221; - q[3][3] = -a41 * a1223_1322 + a42 * a1123_1321 - a43 * a1122_1221; - - double qsqr[4]; - for (int i=0;i<4;i++) - qsqr[i] = q[i][0]*q[i][0] + q[i][1]*q[i][1] + q[i][2]*q[i][2] + q[i][3]*q[i][3]; - - int bi = 0; - double max = 0; - for (int i=0;i<4;i++) - { - if (qsqr[i] > max) - { - bi = i; - max = qsqr[i]; - } - } - - bool too_small = false; - if (qsqr[bi] < evecprec) - { - //if qsqr is still too small, return the identity rotation. - q[bi][0] = 1; - q[bi][1] = 0; - q[bi][2] = 0; - q[bi][3] = 0; - too_small = true; - } - else - { - double normq = sqrt(qsqr[bi]); - q[bi][0] /= normq; - q[bi][1] /= normq; - q[bi][2] /= normq; - q[bi][3] /= normq; - } - - memcpy(qopt, q[bi], 4 * sizeof(double)); - return !too_small; -} - -int polar_decomposition_3x3(double* _A, bool right_sided, double* U, double* P) -{ - double A[9]; - memcpy(A, _A, 9 * sizeof(double)); - - double det = matrix_determinant_3x3(A); - if (det < 0) - flip_matrix(A); - - double q[4]; - double nrmsdsq = 0; - optimal_quaternion(A, true, -1, &nrmsdsq, q); - q[0] = -q[0]; - quaternion_to_rotation_matrix(q, U); - - if (det < 0) - flip_matrix(U); - - double UT[9] = {U[0], U[3], U[6], U[1], U[4], U[7], U[2], U[5], U[8]}; - - if (right_sided) - matmul_3x3(UT, _A, P); - else - matmul_3x3(_A, UT, P); - - return 0; -} - -void InnerProduct(double *A, int num, const double (*coords1)[3], double (*coords2)[3], int8_t* permutation) -{ - A[0] = A[1] = A[2] = A[3] = A[4] = A[5] = A[6] = A[7] = A[8] = 0.0; - - for (int i = 0; i < num; ++i) - { - double x1 = coords1[i][0]; - double y1 = coords1[i][1]; - double z1 = coords1[i][2]; - - double x2 = coords2[permutation[i]][0]; - double y2 = coords2[permutation[i]][1]; - double z2 = coords2[permutation[i]][2]; - - A[0] += x1 * x2; - A[1] += x1 * y2; - A[2] += x1 * z2; - - A[3] += y1 * x2; - A[4] += y1 * y2; - A[5] += y1 * z2; - - A[6] += z1 * x2; - A[7] += z1 * y2; - A[8] += z1 * z2; - } -} - -int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, double* U) -{ - optimal_quaternion(A, false, E0, p_nrmsdsq, q); - quaternion_to_rotation_matrix(q, U); - return 0; -} - diff --git a/src/USER-PTM/polar.h b/src/USER-PTM/polar.h deleted file mode 100644 index 3ec025b806..0000000000 --- a/src/USER-PTM/polar.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef POLAR_H -#define POLAR_H - -#include -#include - -int polar_decomposition_3x3(double* _A, bool right_sided, double* U, double* P); -void InnerProduct(double *A, int num, const double (*coords1)[3], double (*coords2)[3], int8_t* permutation); -int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, double* U); - -#endif - diff --git a/src/PTM/ptm_alloy_types.cpp b/src/USER-PTM/ptm_alloy_types.cpp similarity index 100% rename from src/PTM/ptm_alloy_types.cpp rename to src/USER-PTM/ptm_alloy_types.cpp diff --git a/src/PTM/ptm_alloy_types.h b/src/USER-PTM/ptm_alloy_types.h similarity index 100% rename from src/PTM/ptm_alloy_types.h rename to src/USER-PTM/ptm_alloy_types.h diff --git a/src/PTM/ptm_canonical_coloured.cpp b/src/USER-PTM/ptm_canonical_coloured.cpp similarity index 100% rename from src/PTM/ptm_canonical_coloured.cpp rename to src/USER-PTM/ptm_canonical_coloured.cpp diff --git a/src/PTM/ptm_canonical_coloured.h b/src/USER-PTM/ptm_canonical_coloured.h similarity index 100% rename from src/PTM/ptm_canonical_coloured.h rename to src/USER-PTM/ptm_canonical_coloured.h diff --git a/src/PTM/ptm_convex_hull_incremental.cpp b/src/USER-PTM/ptm_convex_hull_incremental.cpp similarity index 100% rename from src/PTM/ptm_convex_hull_incremental.cpp rename to src/USER-PTM/ptm_convex_hull_incremental.cpp diff --git a/src/PTM/ptm_convex_hull_incremental.h b/src/USER-PTM/ptm_convex_hull_incremental.h similarity index 100% rename from src/PTM/ptm_convex_hull_incremental.h rename to src/USER-PTM/ptm_convex_hull_incremental.h diff --git a/src/PTM/ptm_deformation_gradient.cpp b/src/USER-PTM/ptm_deformation_gradient.cpp similarity index 100% rename from src/PTM/ptm_deformation_gradient.cpp rename to src/USER-PTM/ptm_deformation_gradient.cpp diff --git a/src/PTM/ptm_deformation_gradient.h b/src/USER-PTM/ptm_deformation_gradient.h similarity index 100% rename from src/PTM/ptm_deformation_gradient.h rename to src/USER-PTM/ptm_deformation_gradient.h diff --git a/src/USER-PTM/ptm_functions.h b/src/USER-PTM/ptm_functions.h index 69141a37c4..cd67d4940d 100644 --- a/src/USER-PTM/ptm_functions.h +++ b/src/USER-PTM/ptm_functions.h @@ -3,7 +3,7 @@ #include #include -#include "initialize_data.h" +#include "ptm_initialize_data.h" #include "ptm_constants.h" diff --git a/src/PTM/ptm_fundamental_mappings.h b/src/USER-PTM/ptm_fundamental_mappings.h similarity index 100% rename from src/PTM/ptm_fundamental_mappings.h rename to src/USER-PTM/ptm_fundamental_mappings.h diff --git a/src/PTM/ptm_graph_data.cpp b/src/USER-PTM/ptm_graph_data.cpp similarity index 100% rename from src/PTM/ptm_graph_data.cpp rename to src/USER-PTM/ptm_graph_data.cpp diff --git a/src/PTM/ptm_graph_data.h b/src/USER-PTM/ptm_graph_data.h similarity index 100% rename from src/PTM/ptm_graph_data.h rename to src/USER-PTM/ptm_graph_data.h diff --git a/src/PTM/ptm_graph_tools.cpp b/src/USER-PTM/ptm_graph_tools.cpp similarity index 100% rename from src/PTM/ptm_graph_tools.cpp rename to src/USER-PTM/ptm_graph_tools.cpp diff --git a/src/PTM/ptm_graph_tools.h b/src/USER-PTM/ptm_graph_tools.h similarity index 100% rename from src/PTM/ptm_graph_tools.h rename to src/USER-PTM/ptm_graph_tools.h diff --git a/src/PTM/ptm_index.cpp b/src/USER-PTM/ptm_index.cpp similarity index 100% rename from src/PTM/ptm_index.cpp rename to src/USER-PTM/ptm_index.cpp diff --git a/src/PTM/ptm_initialize_data.cpp b/src/USER-PTM/ptm_initialize_data.cpp similarity index 100% rename from src/PTM/ptm_initialize_data.cpp rename to src/USER-PTM/ptm_initialize_data.cpp diff --git a/src/PTM/ptm_initialize_data.h b/src/USER-PTM/ptm_initialize_data.h similarity index 100% rename from src/PTM/ptm_initialize_data.h rename to src/USER-PTM/ptm_initialize_data.h diff --git a/src/PTM/ptm_neighbour_ordering.cpp b/src/USER-PTM/ptm_neighbour_ordering.cpp similarity index 100% rename from src/PTM/ptm_neighbour_ordering.cpp rename to src/USER-PTM/ptm_neighbour_ordering.cpp diff --git a/src/PTM/ptm_neighbour_ordering.h b/src/USER-PTM/ptm_neighbour_ordering.h similarity index 100% rename from src/PTM/ptm_neighbour_ordering.h rename to src/USER-PTM/ptm_neighbour_ordering.h diff --git a/src/PTM/ptm_normalize_vertices.cpp b/src/USER-PTM/ptm_normalize_vertices.cpp similarity index 100% rename from src/PTM/ptm_normalize_vertices.cpp rename to src/USER-PTM/ptm_normalize_vertices.cpp diff --git a/src/PTM/ptm_normalize_vertices.h b/src/USER-PTM/ptm_normalize_vertices.h similarity index 100% rename from src/PTM/ptm_normalize_vertices.h rename to src/USER-PTM/ptm_normalize_vertices.h diff --git a/src/PTM/ptm_polar.cpp b/src/USER-PTM/ptm_polar.cpp similarity index 100% rename from src/PTM/ptm_polar.cpp rename to src/USER-PTM/ptm_polar.cpp diff --git a/src/PTM/ptm_polar.h b/src/USER-PTM/ptm_polar.h similarity index 100% rename from src/PTM/ptm_polar.h rename to src/USER-PTM/ptm_polar.h diff --git a/src/PTM/ptm_quat.cpp b/src/USER-PTM/ptm_quat.cpp similarity index 100% rename from src/PTM/ptm_quat.cpp rename to src/USER-PTM/ptm_quat.cpp diff --git a/src/PTM/ptm_quat.h b/src/USER-PTM/ptm_quat.h similarity index 100% rename from src/PTM/ptm_quat.h rename to src/USER-PTM/ptm_quat.h diff --git a/src/PTM/ptm_structure_matcher.cpp b/src/USER-PTM/ptm_structure_matcher.cpp similarity index 100% rename from src/PTM/ptm_structure_matcher.cpp rename to src/USER-PTM/ptm_structure_matcher.cpp diff --git a/src/PTM/ptm_structure_matcher.h b/src/USER-PTM/ptm_structure_matcher.h similarity index 100% rename from src/PTM/ptm_structure_matcher.h rename to src/USER-PTM/ptm_structure_matcher.h diff --git a/src/PTM/ptm_voronoi_cell.cpp b/src/USER-PTM/ptm_voronoi_cell.cpp similarity index 100% rename from src/PTM/ptm_voronoi_cell.cpp rename to src/USER-PTM/ptm_voronoi_cell.cpp diff --git a/src/PTM/ptm_voronoi_cell.h b/src/USER-PTM/ptm_voronoi_cell.h similarity index 100% rename from src/PTM/ptm_voronoi_cell.h rename to src/USER-PTM/ptm_voronoi_cell.h diff --git a/src/PTM/ptm_voronoi_config.h b/src/USER-PTM/ptm_voronoi_config.h similarity index 100% rename from src/PTM/ptm_voronoi_config.h rename to src/USER-PTM/ptm_voronoi_config.h diff --git a/src/USER-PTM/quat.cpp b/src/USER-PTM/quat.cpp deleted file mode 100644 index f55aff3d2b..0000000000 --- a/src/USER-PTM/quat.cpp +++ /dev/null @@ -1,396 +0,0 @@ -#include -#include -#include - - -#define SIGN(x) (x >= 0 ? 1 : -1) -#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) -#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) - - -#define SQRT_2 1.4142135623730951454746218587388284504414 -#define HALF_SQRT_2 0.7071067811865474617150084668537601828575 - -#define PHI 1.6180339887498949025257388711906969547272 -#define HALF_PHI 0.8090169943749474512628694355953484773636 - -#define INV_PHI 0.6180339887498947915034364086750429123640 -#define HALF_INV_PHI 0.3090169943749473957517182043375214561820 - -#define SQRT_5_ 2.23606797749978969640917366873127623544061835961152572427089 -#define SQRT_2_3 0.8164965809277260344600790631375275552273 -#define SQRT_1_6 0.4082482904638630172300395315687637776136 - - -double generator_cubic[24][4] = { {1, 0, 0, 0 }, - {0, 1, 0, 0 }, - {0, 0, 1, 0 }, - {0, 0, 0, 1 }, - {0.5, 0.5, 0.5, 0.5 }, - {0.5, 0.5, -0.5, 0.5 }, - {0.5, -0.5, 0.5, 0.5 }, - {0.5, -0.5, -0.5, 0.5 }, - {-0.5, 0.5, 0.5, 0.5 }, - {-0.5, 0.5, -0.5, 0.5 }, - {-0.5, -0.5, 0.5, 0.5 }, - {-0.5, -0.5, -0.5, 0.5 }, - {HALF_SQRT_2, HALF_SQRT_2, 0, 0 }, - {HALF_SQRT_2, 0, HALF_SQRT_2, 0 }, - {HALF_SQRT_2, 0, 0, HALF_SQRT_2 }, - {-HALF_SQRT_2, HALF_SQRT_2, 0, 0 }, - {-HALF_SQRT_2, 0, HALF_SQRT_2, 0 }, - {-HALF_SQRT_2, 0, 0, HALF_SQRT_2 }, - {0, HALF_SQRT_2, HALF_SQRT_2, 0 }, - {0, HALF_SQRT_2, 0, HALF_SQRT_2 }, - {0, 0, HALF_SQRT_2, HALF_SQRT_2 }, - {0, -HALF_SQRT_2, HALF_SQRT_2, 0 }, - {0, -HALF_SQRT_2, 0, HALF_SQRT_2 }, - {0, 0, -HALF_SQRT_2, HALF_SQRT_2 } }; - -double generator_diamond_cubic[12][4] = { {1, 0, 0, 0 }, - {0, 1, 0, 0 }, - {0, 0, 1, 0 }, - {0, 0, 0, 1 }, - {0.5, 0.5, 0.5, 0.5 }, - {0.5, 0.5, -0.5, 0.5 }, - {0.5, -0.5, 0.5, 0.5 }, - {0.5, -0.5, -0.5, 0.5 }, - {-0.5, 0.5, 0.5, 0.5 }, - {-0.5, 0.5, -0.5, 0.5 }, - {-0.5, -0.5, 0.5, 0.5 }, - {-0.5, -0.5, -0.5, 0.5 } }; - -double generator_hcp[6][4] = { {1, 0, 0, 0}, - {0.5, 0.5, 0.5, 0.5}, - {0.5, -0.5, -0.5, -0.5}, - {0, SQRT_2_3, -SQRT_1_6, -SQRT_1_6}, - {0, SQRT_1_6, -SQRT_2_3, SQRT_1_6}, - {0, SQRT_1_6, SQRT_1_6, -SQRT_2_3} }; - -double generator_diamond_hexagonal[3][4] = { {1, 0, 0, 0}, - {0.5, 0.5, 0.5, 0.5}, - {0.5, -0.5, -0.5, -0.5} }; - -double generator_icosahedral[60][4] = { {1, 0, 0, 0}, - {HALF_PHI, -HALF_INV_PHI, -0.5, 0}, - {HALF_PHI, 0, -HALF_INV_PHI, -0.5}, - {HALF_PHI, -0.5, 0, -HALF_INV_PHI}, - {HALF_PHI, HALF_INV_PHI, -0.5, 0}, - {HALF_PHI, 0, HALF_INV_PHI, -0.5}, - {HALF_PHI, -0.5, 0, HALF_INV_PHI}, - {HALF_PHI, 0.5, 0, -HALF_INV_PHI}, - {HALF_PHI, 0, -HALF_INV_PHI, 0.5}, - {HALF_PHI, -HALF_INV_PHI, 0.5, 0}, - {HALF_PHI, 0, HALF_INV_PHI, 0.5}, - {HALF_PHI, HALF_INV_PHI, 0.5, 0}, - {HALF_PHI, 0.5, 0, HALF_INV_PHI}, - {0.5, HALF_PHI, -HALF_INV_PHI, 0}, - {0.5, HALF_PHI, HALF_INV_PHI, 0}, - {0.5, 0.5, 0.5, 0.5}, - {0.5, 0.5, 0.5, -0.5}, - {0.5, 0.5, -0.5, 0.5}, - {0.5, 0.5, -0.5, -0.5}, - {0.5, HALF_INV_PHI, 0, HALF_PHI}, - {0.5, HALF_INV_PHI, 0, -HALF_PHI}, - {0.5, 0, HALF_PHI, -HALF_INV_PHI}, - {0.5, 0, HALF_PHI, HALF_INV_PHI}, - {0.5, 0, -HALF_PHI, -HALF_INV_PHI}, - {0.5, 0, -HALF_PHI, HALF_INV_PHI}, - {0.5, -HALF_INV_PHI, 0, HALF_PHI}, - {0.5, -HALF_INV_PHI, 0, -HALF_PHI}, - {0.5, -0.5, 0.5, 0.5}, - {0.5, -0.5, 0.5, -0.5}, - {0.5, -0.5, -0.5, 0.5}, - {0.5, -0.5, -0.5, -0.5}, - {0.5, -HALF_PHI, -HALF_INV_PHI, 0}, - {0.5, -HALF_PHI, HALF_INV_PHI, 0}, - {HALF_INV_PHI, -HALF_PHI, 0, -0.5}, - {HALF_INV_PHI, 0, -0.5, -HALF_PHI}, - {HALF_INV_PHI, -0.5, -HALF_PHI, 0}, - {HALF_INV_PHI, 0, 0.5, -HALF_PHI}, - {HALF_INV_PHI, -HALF_PHI, 0, 0.5}, - {HALF_INV_PHI, 0.5, -HALF_PHI, 0}, - {HALF_INV_PHI, HALF_PHI, 0, -0.5}, - {HALF_INV_PHI, -0.5, HALF_PHI, 0}, - {HALF_INV_PHI, 0, -0.5, HALF_PHI}, - {HALF_INV_PHI, HALF_PHI, 0, 0.5}, - {HALF_INV_PHI, 0, 0.5, HALF_PHI}, - {HALF_INV_PHI, 0.5, HALF_PHI, 0}, - {0, 1, 0, 0}, - {0, HALF_PHI, -0.5, HALF_INV_PHI}, - {0, HALF_PHI, -0.5, -HALF_INV_PHI}, - {0, HALF_PHI, 0.5, HALF_INV_PHI}, - {0, HALF_PHI, 0.5, -HALF_INV_PHI}, - {0, 0.5, HALF_INV_PHI, -HALF_PHI}, - {0, 0.5, HALF_INV_PHI, HALF_PHI}, - {0, 0.5, -HALF_INV_PHI, -HALF_PHI}, - {0, 0.5, -HALF_INV_PHI, HALF_PHI}, - {0, HALF_INV_PHI, -HALF_PHI, 0.5}, - {0, HALF_INV_PHI, -HALF_PHI, -0.5}, - {0, HALF_INV_PHI, HALF_PHI, 0.5}, - {0, HALF_INV_PHI, HALF_PHI, -0.5}, - {0, 0, 1, 0}, - {0, 0, 0, 1} }; - -static void quat_rot(double* r, double* a, double* b) -{ - b[0] = (r[0] * a[0] - r[1] * a[1] - r[2] * a[2] - r[3] * a[3]); - b[1] = (r[0] * a[1] + r[1] * a[0] + r[2] * a[3] - r[3] * a[2]); - b[2] = (r[0] * a[2] - r[1] * a[3] + r[2] * a[0] + r[3] * a[1]); - b[3] = (r[0] * a[3] + r[1] * a[2] - r[2] * a[1] + r[3] * a[0]); -} - -static int rotate_quaternion_into_fundamental_zone(int num_generators, double (*generator)[4], double* q) -{ - double max = 0.0; - int i = 0, bi = -1; - for (i=0;i max) - { - max = t; - bi = i; - } - } - - double f[4]; - quat_rot(q, generator[bi], f); - memcpy(q, &f, 4 * sizeof(double)); - if (q[0] < 0) - { - q[0] = -q[0]; - q[1] = -q[1]; - q[2] = -q[2]; - q[3] = -q[3]; - } - - return bi; -} - -int rotate_quaternion_into_cubic_fundamental_zone(double* q) -{ - return rotate_quaternion_into_fundamental_zone(24, generator_cubic, q); -} - -int rotate_quaternion_into_diamond_cubic_fundamental_zone(double* q) -{ - return rotate_quaternion_into_fundamental_zone(12, generator_diamond_cubic, q); -} - -int rotate_quaternion_into_icosahedral_fundamental_zone(double* q) -{ - return rotate_quaternion_into_fundamental_zone(60, generator_icosahedral, q); -} - -int rotate_quaternion_into_hcp_fundamental_zone(double* q) -{ - return rotate_quaternion_into_fundamental_zone(6, generator_hcp, q); -} - -int rotate_quaternion_into_diamond_hexagonal_fundamental_zone(double* q) -{ - return rotate_quaternion_into_fundamental_zone(3, generator_diamond_hexagonal, q); -} - -double quat_dot(double* a, double* b) -{ - return a[0] * b[0] - + a[1] * b[1] - + a[2] * b[2] - + a[3] * b[3]; -} - -double quat_size(double* q) -{ - return sqrt(quat_dot(q, q)); -} - -void normalize_quaternion(double* q) -{ - double size = quat_size(q); - - q[0] /= size; - q[1] /= size; - q[2] /= size; - q[3] /= size; -} - -void rotation_matrix_to_quaternion(double* u, double* q) -{ - double r11 = u[0]; - double r12 = u[1]; - double r13 = u[2]; - double r21 = u[3]; - double r22 = u[4]; - double r23 = u[5]; - double r31 = u[6]; - double r32 = u[7]; - double r33 = u[8]; - - q[0] = (1.0 + r11 + r22 + r33) / 4.0; - q[1] = (1.0 + r11 - r22 - r33) / 4.0; - q[2] = (1.0 - r11 + r22 - r33) / 4.0; - q[3] = (1.0 - r11 - r22 + r33) / 4.0; - - q[0] = sqrt(MAX(0, q[0])); - q[1] = sqrt(MAX(0, q[1])); - q[2] = sqrt(MAX(0, q[2])); - q[3] = sqrt(MAX(0, q[3])); - - double m0 = MAX(q[0], q[1]); - double m1 = MAX(q[2], q[3]); - double max = MAX(m0, m1); - - int i = 0; - for (i=0;i<4;i++) - if (q[i] == max) - break; - - if (i == 0) - { - q[1] *= SIGN(r32 - r23); - q[2] *= SIGN(r13 - r31); - q[3] *= SIGN(r21 - r12); - } - else if (i == 1) - { - q[0] *= SIGN(r32 - r23); - q[2] *= SIGN(r21 + r12); - q[3] *= SIGN(r13 + r31); - } - else if (i == 2) - { - q[0] *= SIGN(r13 - r31); - q[1] *= SIGN(r21 + r12); - q[3] *= SIGN(r32 + r23); - } - else if (i == 3) - { - q[0] *= SIGN(r21 - r12); - q[1] *= SIGN(r31 + r13); - q[2] *= SIGN(r32 + r23); - } - - normalize_quaternion(q); -} - -void quaternion_to_rotation_matrix(double* q, double* u) -{ - double a = q[0]; - double b = q[1]; - double c = q[2]; - double d = q[3]; - - u[0] = a*a + b*b - c*c - d*d; - u[1] = 2*b*c - 2*a*d; - u[2] = 2*b*d + 2*a*c; - - u[3] = 2*b*c + 2*a*d; - u[4] = a*a - b*b + c*c - d*d; - u[5] = 2*c*d - 2*a*b; - - u[6] = 2*b*d - 2*a*c; - u[7] = 2*c*d + 2*a*b; - u[8] = a*a - b*b - c*c + d*d; -} - -double quat_quick_misorientation(double* q1, double* q2) -{ - double t = quat_dot(q1, q2); - t = MIN(1, MAX(-1, t)); - return 2 * t * t - 1; -} - -double quat_misorientation(double* q1, double* q2) -{ - return acos(quat_quick_misorientation(q1, q2)); -} - - -double quat_quick_disorientation_cubic(double* q0, double* q1) -{ - double qrot[4]; - double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; - quat_rot(qinv, q1, qrot); - - rotate_quaternion_into_cubic_fundamental_zone(qrot); - double t = qrot[0]; - t = MIN(1, MAX(-1, t)); - return 2 * t * t - 1; -} - -double quat_disorientation_cubic(double* q0, double* q1) -{ - return acos(quat_quick_disorientation_cubic(q0, q1)); -} - -double quat_quick_disorientation_diamond_cubic(double* q0, double* q1) -{ - double qrot[4]; - double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; - quat_rot(qinv, q1, qrot); - - rotate_quaternion_into_diamond_cubic_fundamental_zone(qrot); - double t = qrot[0]; - t = MIN(1, MAX(-1, t)); - return 2 * t * t - 1; -} - -double quat_disorientation_diamond_cubic(double* q0, double* q1) -{ - return acos(quat_quick_disorientation_diamond_cubic(q0, q1)); -} - -double quat_quick_disorientation_hcp(double* q0, double* q1) -{ - double qrot[4]; - double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; - quat_rot(qinv, q1, qrot); - - rotate_quaternion_into_hcp_fundamental_zone(qrot); - double t = qrot[0]; - t = MIN(1, MAX(-1, t)); - return 2 * t * t - 1; -} - -double quat_disorientation_hcp(double* q0, double* q1) -{ - return acos(quat_quick_disorientation_hcp(q0, q1)); -} - -double quat_quick_disorientation_diamond_hexagonal(double* q0, double* q1) -{ - double qrot[4]; - double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; - quat_rot(qinv, q1, qrot); - - rotate_quaternion_into_diamond_hexagonal_fundamental_zone(qrot); - double t = qrot[0]; - t = MIN(1, MAX(-1, t)); - return 2 * t * t - 1; -} - -double quat_disorientation_diamond_hexagonal(double* q0, double* q1) -{ - return acos(quat_quick_disorientation_diamond_hexagonal(q0, q1)); -} - -double quat_quick_disorientation_icosahedral(double* q0, double* q1) -{ - double qrot[4]; - double qinv[4] = {q0[0], -q0[1], -q0[2], -q0[3]}; - quat_rot(qinv, q1, qrot); - - rotate_quaternion_into_icosahedral_fundamental_zone(qrot); - double t = qrot[0]; - t = MIN(1, MAX(-1, t)); - return 2 * t * t - 1; -} - -double quat_disorientation_icosahedral(double* q0, double* q1) -{ - return acos(quat_quick_disorientation_icosahedral(q0, q1)); -} - diff --git a/src/USER-PTM/quat.h b/src/USER-PTM/quat.h deleted file mode 100644 index 725086322c..0000000000 --- a/src/USER-PTM/quat.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef QUAT_H -#define QUAT_H - -int rotate_quaternion_into_cubic_fundamental_zone(double* q); -int rotate_quaternion_into_diamond_cubic_fundamental_zone(double* q); -int rotate_quaternion_into_icosahedral_fundamental_zone(double* q); -int rotate_quaternion_into_hcp_fundamental_zone(double* q); -int rotate_quaternion_into_diamond_hexagonal_fundamental_zone(double* q); - -void normalize_quaternion(double* q); -void quaternion_to_rotation_matrix(double* q, double* U); -void rotation_matrix_to_quaternion(double* u, double* q); -double quat_dot(double* a, double* b); -double quat_quick_misorientation(double* q1, double* q2); -double quat_misorientation(double* q1, double* q2); - -double quat_quick_disorientation_cubic(double* q0, double* q1); -double quat_disorientation_cubic(double* q0, double* q1); -double quat_quick_disorientation_diamond_cubic(double* q0, double* q1); -double quat_disorientation_diamond_cubic(double* q0, double* q1); -double quat_quick_disorientation_hcp(double* q0, double* q1); -double quat_disorientation_hcp(double* q0, double* q1); -double quat_quick_disorientation_diamond_hexagonal(double* q0, double* q1); -double quat_disorientation_diamond_hexagonal(double* q0, double* q1); -double quat_quick_disorientation_icosahedral(double* q0, double* q1); -double quat_disorientation_icosahedral(double* q0, double* q1); - -#endif - - - - diff --git a/src/USER-PTM/structure_matcher.cpp b/src/USER-PTM/structure_matcher.cpp deleted file mode 100644 index dad8e3599a..0000000000 --- a/src/USER-PTM/structure_matcher.cpp +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "convex_hull_incremental.h" -#include "canonical_coloured.h" -#include "graph_data.h" -#include "graph_tools.h" -#include "normalize_vertices.h" -#include "polar.h" -#include "structure_matcher.h" -#include "ptm_constants.h" - - -static double calc_rmsd(int num_points, const double (*ideal_points)[3], double (*normalized)[3], int8_t* mapping, - double G1, double G2, double E0, double* q, double* p_scale) -{ - double A0[9]; - InnerProduct(A0, num_points, ideal_points, normalized, mapping); - - double nrmsdsq, rot[9]; - FastCalcRMSDAndRotation(A0, E0, &nrmsdsq, q, rot); - - double k0 = 0; - for (int i=0;inum_nbrs + 1; - const double (*ideal_points)[3] = s->points; - int8_t inverse_labelling[PTM_MAX_POINTS]; - int8_t mapping[PTM_MAX_POINTS]; - - for (int i=0; inum_graphs;i++) - { - if (hash != s->graphs[i].hash) - continue; - - graph_t* gref = &s->graphs[i]; - for (int j = 0;jnum_automorphisms;j++) - { - for (int k=0;kautomorphism_index + j][k]] = inverse_labelling[ gref->canonical_labelling[k] ]; - - double q[4], scale = 0; - double rmsd = calc_rmsd(num_points, ideal_points, normalized, mapping, G1, G2, E0, q, &scale); - if (rmsd < res->rmsd) - { - res->rmsd = rmsd; - res->scale = scale; - res->ref_struct = s; - memcpy(res->q, q, 4 * sizeof(double)); - memcpy(res->mapping, mapping, sizeof(int8_t) * num_points); - } - } - } -} - -int match_general(const refdata_t* s, double (*ch_points)[3], double (*points)[3], convexhull_t* ch, result_t* res) -{ - int8_t degree[PTM_MAX_NBRS]; - int8_t facets[PTM_MAX_FACETS][3]; - - int ret = get_convex_hull(s->num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); - ch->ok = ret >= 0; - if (ret != 0) - return PTM_NO_ERROR; - - if (ch->num_facets != s->num_facets) - return PTM_NO_ERROR; //incorrect number of facets in convex hull - - int max_degree = graph_degree(s->num_facets, facets, s->num_nbrs, degree); - if (max_degree > s->max_degree) - return PTM_NO_ERROR; - - if (s->type == PTM_MATCH_SC) - for (int i = 0;inum_nbrs;i++) - if (degree[i] != 4) - return PTM_NO_ERROR; - - double normalized[PTM_MAX_POINTS][3]; - subtract_barycentre(s->num_nbrs + 1, points, normalized); - - int8_t code[2 * PTM_MAX_EDGES]; - int8_t colours[PTM_MAX_POINTS] = {0}; - int8_t canonical_labelling[PTM_MAX_POINTS]; - uint64_t hash = 0; - ret = canonical_form_coloured(s->num_facets, facets, s->num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); - if (ret != PTM_NO_ERROR) - return ret; - - check_graphs(s, hash, canonical_labelling, normalized, res); - return PTM_NO_ERROR; -} - -int match_fcc_hcp_ico(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res) -{ - int num_nbrs = structure_fcc.num_nbrs; - int num_facets = structure_fcc.num_facets; - int max_degree = structure_fcc.max_degree; - - int8_t degree[PTM_MAX_NBRS]; - int8_t facets[PTM_MAX_FACETS][3]; - - int ret = get_convex_hull(num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); - ch->ok = ret >= 0; - if (ret != 0) - return PTM_NO_ERROR; - - if (ch->num_facets != num_facets) - return PTM_NO_ERROR; //incorrect number of facets in convex hull - - int _max_degree = graph_degree(num_facets, facets, num_nbrs, degree); - if (_max_degree > max_degree) - return PTM_NO_ERROR; - - double normalized[PTM_MAX_POINTS][3]; - subtract_barycentre(num_nbrs + 1, points, normalized); - - int8_t code[2 * PTM_MAX_EDGES]; - int8_t colours[PTM_MAX_POINTS] = {0}; - int8_t canonical_labelling[PTM_MAX_POINTS]; - uint64_t hash = 0; - ret = canonical_form_coloured(num_facets, facets, num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); - if (ret != PTM_NO_ERROR) - return ret; - - if (flags & PTM_CHECK_FCC) check_graphs(&structure_fcc, hash, canonical_labelling, normalized, res); - if (flags & PTM_CHECK_HCP) check_graphs(&structure_hcp, hash, canonical_labelling, normalized, res); - if (flags & PTM_CHECK_ICO) check_graphs(&structure_ico, hash, canonical_labelling, normalized, res); - return PTM_NO_ERROR; -} - -int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res) -{ - int num_nbrs = structure_dcub.num_nbrs; - int num_facets = structure_fcc.num_facets; - int max_degree = structure_dcub.max_degree; - - - int8_t facets[PTM_MAX_FACETS][3]; - int ret = get_convex_hull(num_nbrs + 1, (const double (*)[3])ch_points, ch, facets); - ch->ok = ret >= 0; - if (ret != 0) - return PTM_NO_ERROR; - - //check for facets with multiple inner atoms - bool inverted[4] = {false, false, false, false}; - for (int i=0;inum_facets;i++) - { - int n = 0; - for (int j=0;j<3;j++) - { - if (facets[i][j] <= 3) - { - inverted[facets[i][j]] = true; - n++; - } - } - if (n > 1) - return PTM_NO_ERROR; - } - - int num_inverted = 0; - for (int i=0;i<4;i++) - num_inverted += inverted[i] ? 1 : 0; - - if (ch->num_facets != num_facets + 2 * num_inverted) - return PTM_NO_ERROR; //incorrect number of facets in convex hull - - int8_t degree[PTM_MAX_NBRS]; - int _max_degree = graph_degree(num_facets, facets, num_nbrs, degree); - if (_max_degree > max_degree) - return PTM_NO_ERROR; - - int num_found = 0; - int8_t toadd[4][3]; - for (int i=0;inum_facets;i++) - { - int a = facets[i][0]; - int b = facets[i][1]; - int c = facets[i][2]; - if (a <= 3 || b <= 3 || c <= 3) - continue; - - int i0 = (a - 4) / 3; - int i1 = (b - 4) / 3; - int i2 = (c - 4) / 3; - - if (i0 == i1 && i0 == i2) - { - if (num_found + num_inverted >= 4) - return PTM_NO_ERROR; - - toadd[num_found][0] = a; - toadd[num_found][1] = b; - toadd[num_found][2] = c; - num_found++; - - memcpy(&facets[i], &facets[ch->num_facets - 1], 3 * sizeof(int8_t)); - ch->num_facets--; - i--; - } - } - - if (num_found + num_inverted != 4) - return PTM_NO_ERROR; - - for (int i=0;inum_facets][0] = i0; - facets[ch->num_facets][1] = b; - facets[ch->num_facets][2] = c; - ch->num_facets++; - - facets[ch->num_facets][0] = a; - facets[ch->num_facets][1] = i0; - facets[ch->num_facets][2] = c; - ch->num_facets++; - - facets[ch->num_facets][0] = a; - facets[ch->num_facets][1] = b; - facets[ch->num_facets][2] = i0; - ch->num_facets++; - } - - _max_degree = graph_degree(ch->num_facets, facets, num_nbrs, degree); - if (_max_degree > max_degree) - return PTM_NO_ERROR; - - double normalized[PTM_MAX_POINTS][3]; - subtract_barycentre(num_nbrs + 1, points, normalized); - - int8_t code[2 * PTM_MAX_EDGES]; - int8_t colours[PTM_MAX_POINTS] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int8_t canonical_labelling[PTM_MAX_POINTS]; - uint64_t hash = 0; - ret = canonical_form_coloured(ch->num_facets, facets, num_nbrs, degree, colours, canonical_labelling, &code[0], &hash); - if (ret != PTM_NO_ERROR) - return ret; - - if (flags & PTM_CHECK_DCUB) check_graphs(&structure_dcub, hash, canonical_labelling, normalized, res); - if (flags & PTM_CHECK_DHEX) check_graphs(&structure_dhex, hash, canonical_labelling, normalized, res); - - return PTM_NO_ERROR; -} - diff --git a/src/USER-PTM/structure_matcher.h b/src/USER-PTM/structure_matcher.h deleted file mode 100644 index 25e80a94e1..0000000000 --- a/src/USER-PTM/structure_matcher.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef STRUCTURE_MATCHER_H -#define STRUCTURE_MATCHER_H - -#include "initialize_data.h" -#include "ptm_constants.h" - -typedef struct -{ - double rmsd; - double scale; - double q[4]; //rotation in quaternion form (rigid body transformation) - int8_t mapping[PTM_MAX_POINTS]; - const refdata_t* ref_struct; -} result_t; - -int match_general(const refdata_t* s, double (*ch_points)[3], double (*points)[3], convexhull_t* ch, result_t* res); -int match_fcc_hcp_ico(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); -int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); - -#endif - From 6e546ef5af0c734da053d752fe1f25e29d34ffce Mon Sep 17 00:00:00 2001 From: pmla Date: Thu, 20 Sep 2018 14:20:58 -0400 Subject: [PATCH 06/13] added ptm namespace --- src/USER-PTM/ptm_alloy_types.cpp | 3 ++ src/USER-PTM/ptm_alloy_types.h | 4 ++ src/USER-PTM/ptm_canonical_coloured.cpp | 3 ++ src/USER-PTM/ptm_canonical_coloured.h | 3 ++ src/USER-PTM/ptm_convex_hull_incremental.cpp | 3 ++ src/USER-PTM/ptm_convex_hull_incremental.h | 3 ++ src/USER-PTM/ptm_deformation_gradient.cpp | 3 ++ src/USER-PTM/ptm_deformation_gradient.h | 4 ++ src/USER-PTM/ptm_fundamental_mappings.h | 3 ++ src/USER-PTM/ptm_graph_data.cpp | 4 ++ src/USER-PTM/ptm_graph_data.h | 3 ++ src/USER-PTM/ptm_graph_tools.cpp | 4 ++ src/USER-PTM/ptm_graph_tools.h | 4 ++ src/USER-PTM/ptm_index.cpp | 44 ++++++++++---------- src/USER-PTM/ptm_initialize_data.cpp | 26 ++++++------ src/USER-PTM/ptm_initialize_data.h | 3 ++ src/USER-PTM/ptm_neighbour_ordering.cpp | 12 +++--- src/USER-PTM/ptm_neighbour_ordering.h | 4 ++ src/USER-PTM/ptm_normalize_vertices.cpp | 3 ++ src/USER-PTM/ptm_normalize_vertices.h | 4 ++ src/USER-PTM/ptm_polar.cpp | 4 ++ src/USER-PTM/ptm_polar.h | 4 ++ src/USER-PTM/ptm_quat.cpp | 4 ++ src/USER-PTM/ptm_quat.h | 7 ++-- src/USER-PTM/ptm_structure_matcher.cpp | 4 ++ src/USER-PTM/ptm_structure_matcher.h | 5 +++ src/USER-PTM/ptm_voronoi_cell.cpp | 2 +- src/USER-PTM/ptm_voronoi_cell.h | 2 +- src/USER-PTM/ptm_voronoi_config.h | 2 +- 29 files changed, 128 insertions(+), 46 deletions(-) diff --git a/src/USER-PTM/ptm_alloy_types.cpp b/src/USER-PTM/ptm_alloy_types.cpp index e14d06db99..151de3e5b8 100644 --- a/src/USER-PTM/ptm_alloy_types.cpp +++ b/src/USER-PTM/ptm_alloy_types.cpp @@ -2,6 +2,7 @@ #include "ptm_constants.h" #include "ptm_initialize_data.h" +namespace ptm { #define NUM_ALLOY_TYPES 3 static uint32_t typedata[NUM_ALLOY_TYPES][3] = { @@ -99,3 +100,5 @@ int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers) return PTM_ALLOY_NONE; } +} + diff --git a/src/USER-PTM/ptm_alloy_types.h b/src/USER-PTM/ptm_alloy_types.h index 6ea6ed1b8a..559e0a7490 100644 --- a/src/USER-PTM/ptm_alloy_types.h +++ b/src/USER-PTM/ptm_alloy_types.h @@ -3,7 +3,11 @@ #include "ptm_initialize_data.h" +namespace ptm { + int32_t find_alloy_type(const refdata_t* ref, int8_t* mapping, int32_t* numbers); +} + #endif diff --git a/src/USER-PTM/ptm_canonical_coloured.cpp b/src/USER-PTM/ptm_canonical_coloured.cpp index 551f52d7e4..ade8f23b15 100644 --- a/src/USER-PTM/ptm_canonical_coloured.cpp +++ b/src/USER-PTM/ptm_canonical_coloured.cpp @@ -4,6 +4,7 @@ #include "ptm_graph_tools.h" #include "ptm_constants.h" +namespace ptm { static bool weinberg_coloured(int num_nodes, int num_edges, int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS], int8_t* colours, int8_t* best_code, int8_t* canonical_labelling, int a, int b) { @@ -165,3 +166,5 @@ int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, i return PTM_NO_ERROR; } +} + diff --git a/src/USER-PTM/ptm_canonical_coloured.h b/src/USER-PTM/ptm_canonical_coloured.h index e71bb08bfc..f8e2a7af5d 100644 --- a/src/USER-PTM/ptm_canonical_coloured.h +++ b/src/USER-PTM/ptm_canonical_coloured.h @@ -3,7 +3,10 @@ #include +namespace ptm { + int canonical_form_coloured(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree, int8_t* colours, int8_t* canonical_labelling, int8_t* best_code, uint64_t* p_hash); +} #endif diff --git a/src/USER-PTM/ptm_convex_hull_incremental.cpp b/src/USER-PTM/ptm_convex_hull_incremental.cpp index c996b17b58..7c79fd371a 100644 --- a/src/USER-PTM/ptm_convex_hull_incremental.cpp +++ b/src/USER-PTM/ptm_convex_hull_incremental.cpp @@ -6,6 +6,7 @@ #include "ptm_convex_hull_incremental.h" #include "ptm_constants.h" +namespace ptm { #define VISIBLE 1 #define INVISIBLE 2 @@ -361,3 +362,5 @@ int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, return ret; } +} + diff --git a/src/USER-PTM/ptm_convex_hull_incremental.h b/src/USER-PTM/ptm_convex_hull_incremental.h index 563a0c436a..6474723907 100644 --- a/src/USER-PTM/ptm_convex_hull_incremental.h +++ b/src/USER-PTM/ptm_convex_hull_incremental.h @@ -6,6 +6,7 @@ #include #include "ptm_constants.h" +namespace ptm { typedef struct { @@ -23,5 +24,7 @@ typedef struct void add_facet(const double (*points)[3], int a, int b, int c, int8_t* facet, double* plane_normal, double* barycentre); int get_convex_hull(int num_points, const double (*points)[3], convexhull_t* ch, int8_t simplex[][3]); +} + #endif diff --git a/src/USER-PTM/ptm_deformation_gradient.cpp b/src/USER-PTM/ptm_deformation_gradient.cpp index d566d5ca11..fc851920a6 100644 --- a/src/USER-PTM/ptm_deformation_gradient.cpp +++ b/src/USER-PTM/ptm_deformation_gradient.cpp @@ -1,5 +1,6 @@ #include "ptm_deformation_gradient.h" +namespace ptm { void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res) { @@ -35,3 +36,5 @@ void calculate_deformation_gradient(int num_points, const double (*ideal_points) } } +} + diff --git a/src/USER-PTM/ptm_deformation_gradient.h b/src/USER-PTM/ptm_deformation_gradient.h index 7decab4b76..32836da44d 100644 --- a/src/USER-PTM/ptm_deformation_gradient.h +++ b/src/USER-PTM/ptm_deformation_gradient.h @@ -4,6 +4,8 @@ #include #include "ptm_constants.h" +namespace ptm { + void calculate_deformation_gradient(int num_points, const double (*ideal_points)[3], int8_t* mapping, double (*normalized)[3], const double (*penrose)[3], double* F, double* res); //sc @@ -137,6 +139,8 @@ const double penrose_dhex[PTM_NUM_POINTS_DHEX][3] = { { 0, 2 * kdcub, -2 * kdcub }, { 2 * kdcub, 0, -2 * kdcub }, }; +} + #endif diff --git a/src/USER-PTM/ptm_fundamental_mappings.h b/src/USER-PTM/ptm_fundamental_mappings.h index 3dd7c39cbb..35fae7f088 100644 --- a/src/USER-PTM/ptm_fundamental_mappings.h +++ b/src/USER-PTM/ptm_fundamental_mappings.h @@ -3,6 +3,8 @@ #include +namespace ptm { + #define NUM_CUBIC_MAPPINGS 24 #define NUM_ICO_MAPPINGS 60 #define NUM_HEX_MAPPINGS 6 @@ -175,6 +177,7 @@ const int8_t mapping_dhex[NUM_DHEX_MAPPINGS][PTM_MAX_POINTS] = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {0, 1, 3, 4, 2, 6, 7, 5, 11, 13, 12, 14, 16, 15, 8, 9, 10}, {0, 1, 4, 2, 3, 7, 5, 6, 14, 15, 16, 8, 10, 9, 11, 13, 12} }; +} #endif diff --git a/src/USER-PTM/ptm_graph_data.cpp b/src/USER-PTM/ptm_graph_data.cpp index a591dbf993..a742c8b339 100644 --- a/src/USER-PTM/ptm_graph_data.cpp +++ b/src/USER-PTM/ptm_graph_data.cpp @@ -1,6 +1,8 @@ #include "ptm_graph_data.h" +namespace ptm { + int8_t automorphisms[65][17] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1}, @@ -2057,3 +2059,5 @@ graph_t graphs_dhex[NUM_DHEX_GRAPHS] = { }; +} + diff --git a/src/USER-PTM/ptm_graph_data.h b/src/USER-PTM/ptm_graph_data.h index 11f46a471f..251c82d2f5 100644 --- a/src/USER-PTM/ptm_graph_data.h +++ b/src/USER-PTM/ptm_graph_data.h @@ -4,6 +4,7 @@ #include #include "ptm_constants.h" +namespace ptm { typedef struct { @@ -33,5 +34,7 @@ extern graph_t graphs_bcc[NUM_BCC_GRAPHS]; extern graph_t graphs_dcub[NUM_DCUB_GRAPHS]; extern graph_t graphs_dhex[NUM_DHEX_GRAPHS]; +} + #endif diff --git a/src/USER-PTM/ptm_graph_tools.cpp b/src/USER-PTM/ptm_graph_tools.cpp index 89d07fc87a..f6fd34d097 100644 --- a/src/USER-PTM/ptm_graph_tools.cpp +++ b/src/USER-PTM/ptm_graph_tools.cpp @@ -4,6 +4,8 @@ #include "ptm_constants.h" +namespace ptm { + bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]) { memset(common, -1, sizeof(int8_t) * PTM_MAX_NBRS * PTM_MAX_NBRS); @@ -50,3 +52,5 @@ int graph_degree(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degr return max_degree; } +} + diff --git a/src/USER-PTM/ptm_graph_tools.h b/src/USER-PTM/ptm_graph_tools.h index 78934e87c1..7befad526b 100644 --- a/src/USER-PTM/ptm_graph_tools.h +++ b/src/USER-PTM/ptm_graph_tools.h @@ -4,8 +4,12 @@ #include #include "ptm_constants.h" +namespace ptm { + bool build_facet_map(int num_facets, int8_t facets[][3], int8_t common[PTM_MAX_NBRS][PTM_MAX_NBRS]); int graph_degree(int num_facets, int8_t facets[][3], int num_nodes, int8_t* degree); +} + #endif diff --git a/src/USER-PTM/ptm_index.cpp b/src/USER-PTM/ptm_index.cpp index 7b6618848e..24998dadd0 100644 --- a/src/USER-PTM/ptm_index.cpp +++ b/src/USER-PTM/ptm_index.cpp @@ -36,13 +36,13 @@ static double calculate_lattice_constant(int type, double interatomic_distance) static int rotate_into_fundamental_zone(int type, double* q) { - if (type == PTM_MATCH_SC) return rotate_quaternion_into_cubic_fundamental_zone(q); - if (type == PTM_MATCH_FCC) return rotate_quaternion_into_cubic_fundamental_zone(q); - if (type == PTM_MATCH_BCC) return rotate_quaternion_into_cubic_fundamental_zone(q); - if (type == PTM_MATCH_ICO) return rotate_quaternion_into_icosahedral_fundamental_zone(q); - if (type == PTM_MATCH_HCP) return rotate_quaternion_into_hcp_fundamental_zone(q); - if (type == PTM_MATCH_DCUB) return rotate_quaternion_into_diamond_cubic_fundamental_zone(q); - if (type == PTM_MATCH_DHEX) return rotate_quaternion_into_diamond_hexagonal_fundamental_zone(q); + if (type == PTM_MATCH_SC) return ptm::rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_FCC) return ptm::rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_BCC) return ptm::rotate_quaternion_into_cubic_fundamental_zone(q); + if (type == PTM_MATCH_ICO) return ptm::rotate_quaternion_into_icosahedral_fundamental_zone(q); + if (type == PTM_MATCH_HCP) return ptm::rotate_quaternion_into_hcp_fundamental_zone(q); + if (type == PTM_MATCH_DCUB) return ptm::rotate_quaternion_into_diamond_cubic_fundamental_zone(q); + if (type == PTM_MATCH_DHEX) return ptm::rotate_quaternion_into_diamond_hexagonal_fundamental_zone(q); return -1; } @@ -52,8 +52,8 @@ static void order_points(ptm_local_handle_t local_handle, int num_points, double if (topological_ordering) { double normalized_points[PTM_MAX_INPUT_POINTS][3]; - normalize_vertices(num_points, unpermuted_points, normalized_points); - int ret = calculate_neighbour_ordering((void*)local_handle, num_points, (const double (*)[3])normalized_points, ordering); + ptm::normalize_vertices(num_points, unpermuted_points, normalized_points); + int ret = ptm::calculate_neighbour_ordering((void*)local_handle, num_points, (const double (*)[3])normalized_points, ordering); if (ret != 0) topological_ordering = false; } @@ -71,7 +71,7 @@ static void order_points(ptm_local_handle_t local_handle, int num_points, double } } -static void output_data(result_t* res, int num_points, int32_t* unpermuted_numbers, double (*points)[3], int32_t* numbers, int8_t* ordering, +static void output_data(ptm::result_t* res, int num_points, int32_t* unpermuted_numbers, double (*points)[3], int32_t* numbers, int8_t* ordering, int32_t* p_type, int32_t* p_alloy_type, double* p_scale, double* p_rmsd, double* q, double* F, double* F_res, double* U, double* P, int8_t* mapping, double* p_interatomic_distance, double* p_lattice_constant) { @@ -82,13 +82,13 @@ static void output_data(result_t* res, int num_points, int32_t* unpermuted_numbe if (mapping != NULL) memset(mapping, -1, num_points * sizeof(int8_t)); - const refdata_t* ref = res->ref_struct; + const ptm::refdata_t* ref = res->ref_struct; if (ref == NULL) return; *p_type = ref->type; if (p_alloy_type != NULL && unpermuted_numbers != NULL) - *p_alloy_type = find_alloy_type(ref, res->mapping, numbers); + *p_alloy_type = ptm::find_alloy_type(ref, res->mapping, numbers); int bi = rotate_into_fundamental_zone(ref->type, res->q); int8_t temp[PTM_MAX_POINTS]; @@ -101,17 +101,17 @@ static void output_data(result_t* res, int num_points, int32_t* unpermuted_numbe { double scaled_points[PTM_MAX_INPUT_POINTS][3]; - subtract_barycentre(ref->num_nbrs + 1, points, scaled_points); + ptm::subtract_barycentre(ref->num_nbrs + 1, points, scaled_points); for (int i = 0;inum_nbrs + 1;i++) { scaled_points[i][0] *= res->scale; scaled_points[i][1] *= res->scale; scaled_points[i][2] *= res->scale; } - calculate_deformation_gradient(ref->num_nbrs + 1, ref->points, res->mapping, scaled_points, ref->penrose, F, F_res); + ptm::calculate_deformation_gradient(ref->num_nbrs + 1, ref->points, res->mapping, scaled_points, ref->penrose, F, F_res); if (P != NULL && U != NULL) - polar_decomposition_3x3(F, false, U, P); + ptm::polar_decomposition_3x3(F, false, U, P); } if (mapping != NULL) @@ -156,7 +156,7 @@ int ptm_index( ptm_local_handle_t local_handle, int32_t flags, assert(num_points >= PTM_NUM_POINTS_DCUB); int ret = 0; - result_t res; + ptm::result_t res; res.ref_struct = NULL; res.rmsd = INFINITY; @@ -168,32 +168,32 @@ int ptm_index( ptm_local_handle_t local_handle, int32_t flags, double dpoints[PTM_MAX_POINTS][3]; int32_t dnumbers[PTM_MAX_POINTS]; - convexhull_t ch; + ptm::convexhull_t ch; double ch_points[PTM_MAX_INPUT_POINTS][3]; if (flags & (PTM_CHECK_SC | PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO | PTM_CHECK_BCC)) { int num_lpoints = std::min(std::min(PTM_MAX_POINTS, 20), num_points); order_points(local_handle, num_lpoints, unpermuted_points, unpermuted_numbers, topological_ordering, ordering, points, numbers); - normalize_vertices(num_lpoints, points, ch_points); + ptm::normalize_vertices(num_lpoints, points, ch_points); ch.ok = false; if (flags & PTM_CHECK_SC) - ret = match_general(&structure_sc, ch_points, points, &ch, &res); + ret = match_general(&ptm::structure_sc, ch_points, points, &ch, &res); if (flags & (PTM_CHECK_FCC | PTM_CHECK_HCP | PTM_CHECK_ICO)) ret = match_fcc_hcp_ico(ch_points, points, flags, &ch, &res); if (flags & PTM_CHECK_BCC) - ret = match_general(&structure_bcc, ch_points, points, &ch, &res); + ret = match_general(&ptm::structure_bcc, ch_points, points, &ch, &res); } if (flags & (PTM_CHECK_DCUB | PTM_CHECK_DHEX)) { - ret = calculate_diamond_neighbour_ordering(num_points, unpermuted_points, unpermuted_numbers, dordering, dpoints, dnumbers); + ret = ptm::calculate_diamond_neighbour_ordering(num_points, unpermuted_points, unpermuted_numbers, dordering, dpoints, dnumbers); if (ret == 0) { - normalize_vertices(PTM_NUM_NBRS_DCUB + 1, dpoints, ch_points); + ptm::normalize_vertices(PTM_NUM_NBRS_DCUB + 1, dpoints, ch_points); ch.ok = false; ret = match_dcub_dhex(ch_points, dpoints, flags, &ch, &res); diff --git a/src/USER-PTM/ptm_initialize_data.cpp b/src/USER-PTM/ptm_initialize_data.cpp index 6157ff862f..8d96e2a2b7 100644 --- a/src/USER-PTM/ptm_initialize_data.cpp +++ b/src/USER-PTM/ptm_initialize_data.cpp @@ -14,20 +14,20 @@ static void make_facets_clockwise(int num_facets, int8_t (*facets)[3], const dou double origin[3] = {0, 0, 0}; for (int i = 0;inum_graphs;i++) { int8_t code[2 * PTM_MAX_EDGES]; int8_t degree[PTM_MAX_NBRS]; - int _max_degree = graph_degree(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree); + int _max_degree = ptm::graph_degree(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree); assert(_max_degree <= s->max_degree); make_facets_clockwise(s->num_facets, s->graphs[i].facets, &s->points[1]); - int ret = canonical_form_coloured(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree, colours, s->graphs[i].canonical_labelling, (int8_t*)&code[0], &s->graphs[i].hash); + int ret = ptm::canonical_form_coloured(s->num_facets, s->graphs[i].facets, s->num_nbrs, degree, colours, s->graphs[i].canonical_labelling, (int8_t*)&code[0], &s->graphs[i].hash); if (ret != 0) return ret; } @@ -44,13 +44,13 @@ int ptm_initialize_global() int8_t colours[PTM_MAX_POINTS] = {0}; int8_t dcolours[PTM_MAX_POINTS] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int ret = initialize_graphs(&structure_sc, colours); - ret |= initialize_graphs(&structure_fcc, colours); - ret |= initialize_graphs(&structure_hcp, colours); - ret |= initialize_graphs(&structure_ico, colours); - ret |= initialize_graphs(&structure_bcc, colours); - ret |= initialize_graphs(&structure_dcub, dcolours); - ret |= initialize_graphs(&structure_dhex, dcolours); + int ret = initialize_graphs(&ptm::structure_sc, colours); + ret |= initialize_graphs(&ptm::structure_fcc, colours); + ret |= initialize_graphs(&ptm::structure_hcp, colours); + ret |= initialize_graphs(&ptm::structure_ico, colours); + ret |= initialize_graphs(&ptm::structure_bcc, colours); + ret |= initialize_graphs(&ptm::structure_dcub, dcolours); + ret |= initialize_graphs(&ptm::structure_dhex, dcolours); if (ret == PTM_NO_ERROR) ptm_initialized = true; @@ -61,11 +61,11 @@ int ptm_initialize_global() ptm_local_handle_t ptm_initialize_local() { assert(ptm_initialized); - return (ptm_local_handle_t)voronoi_initialize_local(); + return (ptm_local_handle_t)ptm::voronoi_initialize_local(); } void ptm_uninitialize_local(ptm_local_handle_t ptr) { - voronoi_uninitialize_local(ptr); + ptm::voronoi_uninitialize_local(ptr); } diff --git a/src/USER-PTM/ptm_initialize_data.h b/src/USER-PTM/ptm_initialize_data.h index f381dd864b..5374fbf7d0 100644 --- a/src/USER-PTM/ptm_initialize_data.h +++ b/src/USER-PTM/ptm_initialize_data.h @@ -11,6 +11,8 @@ #include "ptm_convex_hull_incremental.h" +namespace ptm { + typedef struct { int type; @@ -35,6 +37,7 @@ const refdata_t structure_bcc = { PTM_MATCH_BCC, 14, 24, 8, NUM_BCC_GRAPHS, N const refdata_t structure_dcub = { PTM_MATCH_DCUB, 16, 28, 8, NUM_DCUB_GRAPHS, NUM_DCUB_MAPPINGS, graphs_dcub, ptm_template_dcub, penrose_dcub, mapping_dcub }; const refdata_t structure_dhex = { PTM_MATCH_DHEX, 16, 28, 8, NUM_DHEX_GRAPHS, NUM_DHEX_MAPPINGS, graphs_dhex, ptm_template_dhex, penrose_dhex, mapping_dhex }; +} #ifdef __cplusplus extern "C" { diff --git a/src/USER-PTM/ptm_neighbour_ordering.cpp b/src/USER-PTM/ptm_neighbour_ordering.cpp index 6b5ac9601a..c77a779c68 100644 --- a/src/USER-PTM/ptm_neighbour_ordering.cpp +++ b/src/USER-PTM/ptm_neighbour_ordering.cpp @@ -5,9 +5,9 @@ #include #include "ptm_constants.h" #include "ptm_voronoi_cell.h" -using namespace voro; +namespace ptm { typedef struct { @@ -31,7 +31,7 @@ static bool sorthelper_compare(sorthelper_t const& a, sorthelper_t const& b) } //todo: change voronoi code to return errors rather than exiting -static int calculate_voronoi_face_areas(int num_points, const double (*_points)[3], double* normsq, double max_norm, voronoicell_neighbor* v, std::vector& nbr_indices, std::vector& face_areas) +static int calculate_voronoi_face_areas(int num_points, const double (*_points)[3], double* normsq, double max_norm, ptm_voro::voronoicell_neighbor* v, std::vector& nbr_indices, std::vector& face_areas) { const double k = 1000 * max_norm; //todo: reduce this constant v->init(-k,k,-k,k,-k,k); @@ -53,7 +53,7 @@ int calculate_neighbour_ordering(void* _voronoi_handle, int num_points, const do { assert(num_points <= PTM_MAX_INPUT_POINTS); - voronoicell_neighbor* voronoi_handle = (voronoicell_neighbor*)_voronoi_handle; + ptm_voro::voronoicell_neighbor* voronoi_handle = (ptm_voro::voronoicell_neighbor*)_voronoi_handle; double max_norm = 0; double points[PTM_MAX_INPUT_POINTS][3]; @@ -116,13 +116,13 @@ int calculate_neighbour_ordering(void* _voronoi_handle, int num_points, const do void* voronoi_initialize_local() { - voronoicell_neighbor* ptr = new voronoicell_neighbor; + ptm_voro::voronoicell_neighbor* ptr = new ptm_voro::voronoicell_neighbor; return (void*)ptr; } void voronoi_uninitialize_local(void* _ptr) { - voronoicell_neighbor* ptr = (voronoicell_neighbor*)_ptr; + ptm_voro::voronoicell_neighbor* ptr = (ptm_voro::voronoicell_neighbor*)_ptr; delete ptr; } @@ -201,3 +201,5 @@ int calculate_diamond_neighbour_ordering( int num_points, double (*unpermuted_po return 0; } +} + diff --git a/src/USER-PTM/ptm_neighbour_ordering.h b/src/USER-PTM/ptm_neighbour_ordering.h index ce4dfca2c0..e43ced9fd5 100644 --- a/src/USER-PTM/ptm_neighbour_ordering.h +++ b/src/USER-PTM/ptm_neighbour_ordering.h @@ -1,6 +1,8 @@ #ifndef PTM_NEIGHBOUR_ORDERING_H #define PTM_NEIGHBOUR_ORDERING_H +namespace ptm { + int calculate_neighbour_ordering(void* voronoi_handle, int num_points, const double (*_points)[3], int8_t* ordering); int calculate_diamond_neighbour_ordering( int num_points, double (*unpermuted_points)[3], int32_t* unpermuted_numbers, @@ -9,5 +11,7 @@ int calculate_diamond_neighbour_ordering( int num_points, double (*unpermuted_po void* voronoi_initialize_local(); void voronoi_uninitialize_local(void* ptr); +} + #endif diff --git a/src/USER-PTM/ptm_normalize_vertices.cpp b/src/USER-PTM/ptm_normalize_vertices.cpp index 61dca5006f..22e3c1e670 100644 --- a/src/USER-PTM/ptm_normalize_vertices.cpp +++ b/src/USER-PTM/ptm_normalize_vertices.cpp @@ -1,5 +1,6 @@ #include +namespace ptm { void subtract_barycentre(int num, double (*points)[3], double (*normalized)[3]) { @@ -53,3 +54,5 @@ double normalize_vertices(int num, double (*points)[3], double (*normalized)[3]) return scale; } +} + diff --git a/src/USER-PTM/ptm_normalize_vertices.h b/src/USER-PTM/ptm_normalize_vertices.h index 2c7b722752..dc93db94a3 100644 --- a/src/USER-PTM/ptm_normalize_vertices.h +++ b/src/USER-PTM/ptm_normalize_vertices.h @@ -1,8 +1,12 @@ #ifndef PTM_NORMALIZE_VERTICES_H #define PTM_NORMALIZE_VERTICES_H +namespace ptm { + void subtract_barycentre(int num, double (*points)[3], double (*normalized)[3]); double normalize_vertices(int num, double (*points)[3], double (*normalized)[3]); +} + #endif diff --git a/src/USER-PTM/ptm_polar.cpp b/src/USER-PTM/ptm_polar.cpp index 9089b327b9..fa199ca656 100644 --- a/src/USER-PTM/ptm_polar.cpp +++ b/src/USER-PTM/ptm_polar.cpp @@ -91,6 +91,8 @@ #include "ptm_quat.h" +namespace ptm { + static void matmul_3x3(double* A, double* x, double* b) { b[0] = A[0] * x[0] + A[1] * x[3] + A[2] * x[6]; @@ -335,3 +337,5 @@ int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, return 0; } +} + diff --git a/src/USER-PTM/ptm_polar.h b/src/USER-PTM/ptm_polar.h index d5aa3d9540..15d1f185b7 100644 --- a/src/USER-PTM/ptm_polar.h +++ b/src/USER-PTM/ptm_polar.h @@ -4,9 +4,13 @@ #include #include +namespace ptm { + int polar_decomposition_3x3(double* _A, bool right_sided, double* U, double* P); void InnerProduct(double *A, int num, const double (*coords1)[3], double (*coords2)[3], int8_t* permutation); int FastCalcRMSDAndRotation(double *A, double E0, double *p_nrmsdsq, double *q, double* U); +} + #endif diff --git a/src/USER-PTM/ptm_quat.cpp b/src/USER-PTM/ptm_quat.cpp index f55aff3d2b..376cc74901 100644 --- a/src/USER-PTM/ptm_quat.cpp +++ b/src/USER-PTM/ptm_quat.cpp @@ -3,6 +3,8 @@ #include +namespace ptm { + #define SIGN(x) (x >= 0 ? 1 : -1) #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) @@ -394,3 +396,5 @@ double quat_disorientation_icosahedral(double* q0, double* q1) return acos(quat_quick_disorientation_icosahedral(q0, q1)); } +} + diff --git a/src/USER-PTM/ptm_quat.h b/src/USER-PTM/ptm_quat.h index 381c3ce876..74caa2c62c 100644 --- a/src/USER-PTM/ptm_quat.h +++ b/src/USER-PTM/ptm_quat.h @@ -1,6 +1,8 @@ #ifndef PTM_QUAT_H #define PTM_QUAT_H +namespace ptm { + int rotate_quaternion_into_cubic_fundamental_zone(double* q); int rotate_quaternion_into_diamond_cubic_fundamental_zone(double* q); int rotate_quaternion_into_icosahedral_fundamental_zone(double* q); @@ -25,8 +27,7 @@ double quat_disorientation_diamond_hexagonal(double* q0, double* q1); double quat_quick_disorientation_icosahedral(double* q0, double* q1); double quat_disorientation_icosahedral(double* q0, double* q1); +} + #endif - - - diff --git a/src/USER-PTM/ptm_structure_matcher.cpp b/src/USER-PTM/ptm_structure_matcher.cpp index 7eb0a44143..a86b3670ce 100644 --- a/src/USER-PTM/ptm_structure_matcher.cpp +++ b/src/USER-PTM/ptm_structure_matcher.cpp @@ -15,6 +15,8 @@ #include "ptm_constants.h" +namespace ptm { + static double calc_rmsd(int num_points, const double (*ideal_points)[3], double (*normalized)[3], int8_t* mapping, double G1, double G2, double E0, double* q, double* p_scale) { @@ -292,3 +294,5 @@ int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, return PTM_NO_ERROR; } +} + diff --git a/src/USER-PTM/ptm_structure_matcher.h b/src/USER-PTM/ptm_structure_matcher.h index 4b6f969597..ffaed78e82 100644 --- a/src/USER-PTM/ptm_structure_matcher.h +++ b/src/USER-PTM/ptm_structure_matcher.h @@ -4,6 +4,9 @@ #include "ptm_initialize_data.h" #include "ptm_constants.h" + +namespace ptm { + typedef struct { double rmsd; @@ -17,5 +20,7 @@ int match_general(const refdata_t* s, double (*ch_points)[3], double (*points)[3 int match_fcc_hcp_ico(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); int match_dcub_dhex(double (*ch_points)[3], double (*points)[3], int32_t flags, convexhull_t* ch, result_t* res); +} + #endif diff --git a/src/USER-PTM/ptm_voronoi_cell.cpp b/src/USER-PTM/ptm_voronoi_cell.cpp index 6503ea16c6..ffd7a95ea2 100644 --- a/src/USER-PTM/ptm_voronoi_cell.cpp +++ b/src/USER-PTM/ptm_voronoi_cell.cpp @@ -15,7 +15,7 @@ #include "ptm_voronoi_config.h" #include "ptm_voronoi_cell.h" -namespace voro { +namespace ptm_voro { inline void voro_fatal_error(const char *p,int status) { fprintf(stderr,"voro++: %s\n",p); diff --git a/src/USER-PTM/ptm_voronoi_cell.h b/src/USER-PTM/ptm_voronoi_cell.h index 80a0501b3c..e0284bc56f 100644 --- a/src/USER-PTM/ptm_voronoi_cell.h +++ b/src/USER-PTM/ptm_voronoi_cell.h @@ -17,7 +17,7 @@ #include "ptm_voronoi_config.h" -namespace voro { +namespace ptm_voro { /** \brief A class representing a single Voronoi cell. * diff --git a/src/USER-PTM/ptm_voronoi_config.h b/src/USER-PTM/ptm_voronoi_config.h index 86257e60cc..46c5a4b915 100644 --- a/src/USER-PTM/ptm_voronoi_config.h +++ b/src/USER-PTM/ptm_voronoi_config.h @@ -12,7 +12,7 @@ #ifndef PTM_VOROPP_CONFIG_HH #define PTM_VOROPP_CONFIG_HH -namespace voro { +namespace ptm_voro { // These constants set the initial memory allocation for the Voronoi cell /** The initial memory allocation for the number of vertices. */ From 36c5fb2ec62554996193c6351449feba4e230b33 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 24 Sep 2018 10:33:26 -0400 Subject: [PATCH 07/13] update formatting --- doc/src/pair_coul_shield.txt | 3 ++- doc/src/pair_ilp_graphene_hbn.txt | 22 +++++++++++++--------- doc/src/pair_kolmogorov_crespi_full.txt | 22 ++++++++++++---------- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/doc/src/pair_coul_shield.txt b/doc/src/pair_coul_shield.txt index 8b88d07ece..df04e76de9 100644 --- a/doc/src/pair_coul_shield.txt +++ b/doc/src/pair_coul_shield.txt @@ -38,7 +38,8 @@ charge and molecule ID information is included. Where Tap(r_ij) is the taper function which provides a continuous cutoff (up to third derivative) for inter-atomic separations larger than r_c -"(Leven1)"_#Leven3, "(Leven2)"_#Leven4 and "(Maaravi)"_#Maaravi1. Here {lambda} is the shielding parameter that +"(Leven1)"_#Leven3, "(Leven2)"_#Leven4 and "(Maaravi)"_#Maaravi1. +Here {lambda} is the shielding parameter that eliminates the short-range singularity of the classical mono-polar electrostatic interaction expression "(Maaravi)"_#Maaravi1. diff --git a/doc/src/pair_ilp_graphene_hbn.txt b/doc/src/pair_ilp_graphene_hbn.txt index b7d1c2cdb1..f048b16ccf 100644 --- a/doc/src/pair_ilp_graphene_hbn.txt +++ b/doc/src/pair_ilp_graphene_hbn.txt @@ -25,14 +25,15 @@ pair_coeff * * rebo CH.airebo NULL NULL C pair_coeff * * tersoff BNC.tersoff B N NULL pair_coeff * * ilp/graphene/hbn BNCH.ILP B N C pair_coeff 1 1 coul/shield 0.70 -pair_coeff 1 2 coul/shield 0.69498201415576216335 +pair_coeff 1 2 coul/shield 0.695 pair_coeff 2 2 coul/shield 0.69 :pre [Description:] The {ilp/graphene/hbn} style computes the registry-dependent interlayer -potential (ILP) potential as described in "(Leven1)"_#Leven1, "(Leven2)"_#Leven2 and -"(Maaravi)"_#Maaravi2. The normals are calculated in the way as described +potential (ILP) potential as described in "(Leven1)"_#Leven1, +"(Leven2)"_#Leven2 and "(Maaravi)"_#Maaravi2. +The normals are calculated in the way as described in "(Kolmogorov)"_#Kolmogorov2. :c,image(Eqs/pair_ilp_graphene_hbn.jpg) @@ -62,12 +63,15 @@ NOTE: The parameters presented in the parameter file (e.g. BNCH.ILP), are fitted with taper function by setting the cutoff equal to 16.0 Angstrom. Using different cutoff or taper function should be careful. -NOTE: Two new sets of parameters of ILP for two-dimensional hexagonal Materials are presented in "(Ouyang)"_#Ouyang. -These parameters provide a good description in both short- and long-range interaction regimes. -While the old ILP parameters published in "(Leven2)"_#Leven2 and "(Maaravi)"_#Maaravi2 are -only suitable for long-range interaction regime. This feature is essential for simulations -in high pressure regime (i.e., the interlayer distance is smaller than the equilibrium distance). -The benchmark tests and comparison of these parameters can be found in "(Ouyang)"_#Ouyang. +NOTE: Two new sets of parameters of ILP for two-dimensional hexagonal +Materials are presented in "(Ouyang)"_#Ouyang. These parameters provide +a good description in both short- and long-range interaction regimes. +While the old ILP parameters published in "(Leven2)"_#Leven2 and +"(Maaravi)"_#Maaravi2 are only suitable for long-range interaction +regime. This feature is essential for simulations in high pressure +regime (i.e., the interlayer distance is smaller than the equilibrium +distance). The benchmark tests and comparison of these parameters can +be found in "(Ouyang)"_#Ouyang. This potential must be used in combination with hybrid/overlay. Other interactions can be set to zero using pair_style {none}. diff --git a/doc/src/pair_kolmogorov_crespi_full.txt b/doc/src/pair_kolmogorov_crespi_full.txt index 1fe87dd7ee..df9a9696be 100644 --- a/doc/src/pair_kolmogorov_crespi_full.txt +++ b/doc/src/pair_kolmogorov_crespi_full.txt @@ -53,15 +53,17 @@ and {rcut} are included in the parameter file. {S} is designed to facilitate scaling of energies. {rcut} is designed to build the neighbor list for calculating the normals for each atom pair. -NOTE: Two new sets of parameters of KC potential for hydrocarbons, CH.KC (without the taper function) -and CH_taper.KC (with the taper function) are presented in "(Ouyang)"_#Ouyang1. -The energy for the KC potential with the taper function goes continuously to zero at the cutoff. -The parameters in both CH.KC and CH_taper.KC provide a good description in -both short- and long-range interaction regimes. While the original parameters (CC.KC) -published in "(Kolmogorov)"_#Kolmogorov1 are only suitable for long-range interaction regime. -This feature is essential for simulations in high pressure regime -(i.e., the interlayer distance is smaller than the equilibrium distance). -The benchmark tests and comparison of these parameters can be found in "(Ouyang)"_#Ouyang1. +NOTE: Two new sets of parameters of KC potential for hydrocarbons, CH.KC +(without the taper function) and CH_taper.KC (with the taper function) +are presented in "(Ouyang)"_#Ouyang1. The energy for the KC potential +with the taper function goes continuously to zero at the cutoff. The +parameters in both CH.KC and CH_taper.KC provide a good description in +both short- and long-range interaction regimes. While the original +parameters (CC.KC) published in "(Kolmogorov)"_#Kolmogorov1 are only +suitable for long-range interaction regime. This feature is essential +for simulations in high pressure regime (i.e., the interlayer distance +is smaller than the equilibrium distance). The benchmark tests and +comparison of these parameters can be found in "(Ouyang)"_#Ouyang1. This potential must be used in combination with hybrid/overlay. Other interactions can be set to zero using pair_style {none}. @@ -109,4 +111,4 @@ units. [(Kolmogorov)] A. N. Kolmogorov, V. H. Crespi, Phys. Rev. B 71, 235415 (2005) :link(Ouyang1) -[(Ouyang)] W. Ouyang, D. Mandelli, M. Urbakh and O. Hod, Nano Lett. 18, 6009-6016 (2018). \ No newline at end of file +[(Ouyang)] W. Ouyang, D. Mandelli, M. Urbakh and O. Hod, Nano Lett. 18, 6009-6016 (2018). From aefdcd0f94820a2f41bee0df44bfaeaf0ce5ce43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=BCtter?= Date: Tue, 25 Sep 2018 11:14:42 +0200 Subject: [PATCH 08/13] Silence some warnings --- src/USER-MEAMC/meam_dens_init.cpp | 5 ++--- src/USER-MEAMC/meam_funcs.cpp | 2 +- src/USER-MEAMC/pair_meamc.cpp | 9 +++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/USER-MEAMC/meam_dens_init.cpp b/src/USER-MEAMC/meam_dens_init.cpp index 4bbaa42596..0aa71125c8 100644 --- a/src/USER-MEAMC/meam_dens_init.cpp +++ b/src/USER-MEAMC/meam_dens_init.cpp @@ -101,7 +101,7 @@ MEAM::getscreen(int i, double* scrfcn, double* dscrfcn, double* fcpair, double** double xjtmp, yjtmp, zjtmp, delxik, delyik, delzik, rik2 /*,rik*/; double xktmp, yktmp, zktmp, delxjk, delyjk, delzjk, rjk2 /*,rjk*/; double xik, xjk, sij, fcij, sfcij, dfcij, sikj, dfikj, cikj; - double Cmin, Cmax, delc, /*ebound,*/ rbound, a, coef1, coef2; + double Cmin, Cmax, delc, /*ebound,*/ a, coef1, coef2; double dCikj; double rnorm, fc, dfc, drinv; @@ -129,6 +129,7 @@ MEAM::getscreen(int i, double* scrfcn, double* dscrfcn, double* fcpair, double** rij2 = delxij * delxij + delyij * delyij + delzij * delzij; rij = sqrt(rij2); + const double rbound = this->ebound_meam[elti][eltj] * rij2; if (rij > this->rc_meam) { fcij = 0.0; dfcij = 0.0; @@ -138,7 +139,6 @@ MEAM::getscreen(int i, double* scrfcn, double* dscrfcn, double* fcpair, double** sij = 1.0; // if rjk2 > ebound*rijsq, atom k is definitely outside the ellipse - const double rbound = this->ebound_meam[elti][eltj] * rij2; for (kn = 0; kn < numneigh_full; kn++) { k = firstneigh_full[kn]; eltk = fmap[type[k]]; @@ -193,7 +193,6 @@ MEAM::getscreen(int i, double* scrfcn, double* dscrfcn, double* fcpair, double** if (iszero(sfcij) || iszero(sfcij - 1.0)) goto LABEL_100; - rbound = this->ebound_meam[elti][eltj] * rij2; for (kn = 0; kn < numneigh_full; kn++) { k = firstneigh_full[kn]; if (k == j) continue; diff --git a/src/USER-MEAMC/meam_funcs.cpp b/src/USER-MEAMC/meam_funcs.cpp index 29db27fc4b..1d47dcc1f6 100644 --- a/src/USER-MEAMC/meam_funcs.cpp +++ b/src/USER-MEAMC/meam_funcs.cpp @@ -87,7 +87,7 @@ MEAM::dG_gam(const double gamma, const int ibar, double& dG) const // e.g. gsmooth_factor is 99, {: // gsmooth_switchpoint = -0.99 // G = 0.01*(-0.99/gamma)**99 - double G = 1 / (gsmooth_factor + 1) * pow((gsmooth_switchpoint / gamma), gsmooth_factor); + G = 1 / (gsmooth_factor + 1) * pow((gsmooth_switchpoint / gamma), gsmooth_factor); G = sqrt(G); dG = -gsmooth_factor * G / (2.0 * gamma); return G; diff --git a/src/USER-MEAMC/pair_meamc.cpp b/src/USER-MEAMC/pair_meamc.cpp index ff2a1180b5..b74416a46d 100644 --- a/src/USER-MEAMC/pair_meamc.cpp +++ b/src/USER-MEAMC/pair_meamc.cpp @@ -206,7 +206,7 @@ void PairMEAMC::settings(int narg, char **/*arg*/) void PairMEAMC::coeff(int narg, char **arg) { - int i,j,m,n; + int m,n; if (!allocated) allocate(); @@ -222,7 +222,7 @@ void PairMEAMC::coeff(int narg, char **arg) // elements = list of unique element names if (nelements) { - for (i = 0; i < nelements; i++) delete [] elements[i]; + for (int i = 0; i < nelements; i++) delete [] elements[i]; delete [] elements; delete [] mass; } @@ -231,7 +231,7 @@ void PairMEAMC::coeff(int narg, char **arg) elements = new char*[nelements]; mass = new double[nelements]; - for (i = 0; i < nelements; i++) { + for (int i = 0; i < nelements; i++) { n = strlen(arg[i+3]) + 1; elements[i] = new char[n]; strcpy(elements[i],arg[i+3]); @@ -247,8 +247,9 @@ void PairMEAMC::coeff(int narg, char **arg) // read args that map atom types to MEAM elements // map[i] = which element the Ith atom type is, -1 if not mapped - for (i = 4 + nelements; i < narg; i++) { + for (int i = 4 + nelements; i < narg; i++) { m = i - (4+nelements) + 1; + int j; for (j = 0; j < nelements; j++) if (strcmp(arg[i],elements[j]) == 0) break; if (j < nelements) map[m] = j; From e5ddc909adc491cfb52fe4d7a8d78979918da22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=BCtter?= Date: Tue, 25 Sep 2018 14:19:26 +0200 Subject: [PATCH 09/13] Fully zero-init MEAM data structure --- src/USER-MEAMC/meam_impl.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/USER-MEAMC/meam_impl.cpp b/src/USER-MEAMC/meam_impl.cpp index 25c53785e4..d4a47a4f48 100644 --- a/src/USER-MEAMC/meam_impl.cpp +++ b/src/USER-MEAMC/meam_impl.cpp @@ -34,6 +34,19 @@ MEAM::MEAM(Memory* mem) maxneigh = 0; scrfcn = dscrfcn = fcpair = NULL; + + neltypes = 0; + for (int i = 0; i < maxelt; i++) { + Omega_meam[i] = Z_meam[i] = A_meam[i] = rho0_meam[i] = beta0_meam[i] = + beta1_meam[i]= beta2_meam[i] = beta3_meam[i] = + t0_meam[i] = t1_meam[i] = t2_meam[i] = t3_meam[i] = + rho_ref_meam[i] = ibar_meam[i] = ielt_meam[i] = 0.0; + for (int j = 0; j < maxelt; j++) { + lattce_meam[i][j] = FCC; + Ec_meam[i][j] = re_meam[i][j] = alpha_meam[i][j] = delta_meam[i][j] = Ec_meam[i][j] = ebound_meam[i][j] = attrac_meam[i][j] = repuls_meam[i][j] = 0.0; + nn2_meam[i][j] = zbl_meam[i][j] = eltind[i][j] = 0; + } + } } MEAM::~MEAM() From 93e56c113af8b274ea4504a9e3b284058498b5de Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 25 Sep 2018 09:18:11 -0400 Subject: [PATCH 10/13] add USER-PTM to build system --- cmake/CMakeLists.txt | 13 +++++++------ src/Makefile | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index ce8de0b501..610fb5b57c 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -164,12 +164,13 @@ set(LAMMPS_DEPS) set(LAMMPS_API_DEFINES) set(DEFAULT_PACKAGES ASPHERE BODY CLASS2 COLLOID COMPRESS DIPOLE GRANULAR - KSPACE MANYBODY MC MEAM MESSAGE MISC MOLECULE PERI REAX REPLICA RIGID SHOCK SPIN SNAP - SRD KIM PYTHON MSCG MPIIO VORONOI POEMS LATTE USER-ATC USER-AWPMD USER-BOCS - USER-CGDNA USER-MESO USER-CGSDK USER-COLVARS USER-DIFFRACTION USER-DPD USER-DRUDE - USER-EFF USER-FEP USER-H5MD USER-LB USER-MANIFOLD USER-MEAMC USER-MGPT USER-MISC - USER-MOFFF USER-MOLFILE USER-NETCDF USER-PHONON USER-QTB USER-REAXC USER-SCAFACOS - USER-SMD USER-SMTBQ USER-SPH USER-TALLY USER-UEF USER-VTK USER-QUIP USER-QMMM) + KSPACE MANYBODY MC MEAM MESSAGE MISC MOLECULE PERI REAX REPLICA RIGID SHOCK + SPIN SNAP SRD KIM PYTHON MSCG MPIIO VORONOI POEMS LATTE USER-ATC USER-AWPMD + USER-BOCS USER-CGDNA USER-MESO USER-CGSDK USER-COLVARS USER-DIFFRACTION + USER-DPD USER-DRUDE USER-EFF USER-FEP USER-H5MD USER-LB USER-MANIFOLD + USER-MEAMC USER-MGPT USER-MISC USER-MOFFF USER-MOLFILE USER-NETCDF + USER-PHONON USER-PTM USER-QTB USER-REAXC USER-SCAFACOS USER-SMD USER-SMTBQ + USER-SPH USER-TALLY USER-UEF USER-VTK USER-QUIP USER-QMMM) set(ACCEL_PACKAGES USER-OMP KOKKOS OPT USER-INTEL GPU) set(OTHER_PACKAGES CORESHELL QEQ) foreach(PKG ${DEFAULT_PACKAGES}) diff --git a/src/Makefile b/src/Makefile index 2ee7885562..eefc64b274 100644 --- a/src/Makefile +++ b/src/Makefile @@ -61,7 +61,7 @@ PACKUSER = user-atc user-awpmd user-bocs user-cgdna user-cgsdk user-colvars \ user-diffraction user-dpd user-drude user-eff user-fep user-h5md \ user-intel user-lb user-manifold user-meamc user-meso \ user-mgpt user-misc user-mofff user-molfile \ - user-netcdf user-omp user-phonon user-qmmm user-qtb \ + user-netcdf user-omp user-phonon user-ptm user-qmmm user-qtb \ user-quip user-reaxc user-scafacos user-smd user-smtbq \ user-sph user-tally user-uef user-vtk From 37fe03c0ab7905e11cf3b8ed9dcb4fb0b42d074d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 25 Sep 2018 09:19:09 -0400 Subject: [PATCH 11/13] escape backslash in bibtex string for correct citeme output --- src/USER-PTM/compute_ptm_atom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/USER-PTM/compute_ptm_atom.cpp b/src/USER-PTM/compute_ptm_atom.cpp index b6b4a9786c..eb0138de26 100644 --- a/src/USER-PTM/compute_ptm_atom.cpp +++ b/src/USER-PTM/compute_ptm_atom.cpp @@ -46,7 +46,7 @@ using namespace LAMMPS_NS; static const char cite_user_ptm_package[] = "USER-PTM package:\n\n" "@Article{larsen2016ptm,\n" - " author={Larsen, Peter Mahler and Schmidt, S{\o}ren and Schi{\o}tz, " + " author={Larsen, Peter Mahler and Schmidt, S{\\o}ren and Schi{\\o}tz, " "Jakob},\n" " title={Robust structural identification via polyhedral template " "matching},\n" From e1627caf04eb20d6fcf2282964f025c866b3aad9 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 27 Sep 2018 07:20:03 -0400 Subject: [PATCH 12/13] integrate compute ptm/atom and USER-PTM into the docs --- doc/src/Commands_compute.txt | 1 + doc/src/Packages_details.txt | 20 ++++++++++++++++++++ doc/src/Packages_user.txt | 1 + doc/src/compute_ptm_atom.txt | 6 +++++- doc/src/computes.txt | 1 + doc/src/lammps.book | 1 + 6 files changed, 29 insertions(+), 1 deletion(-) diff --git a/doc/src/Commands_compute.txt b/doc/src/Commands_compute.txt index 028e274c9b..a89f3adf5d 100644 --- a/doc/src/Commands_compute.txt +++ b/doc/src/Commands_compute.txt @@ -95,6 +95,7 @@ KOKKOS, o = USER-OMP, t = OPT. "property/atom"_compute_property_atom.html, "property/chunk"_compute_property_chunk.html, "property/local"_compute_property_local.html, +"ptm/atom"_compute_ptm_atom.html "rdf"_compute_rdf.html, "reduce"_compute_reduce.html, "reduce/region"_compute_reduce.html, diff --git a/doc/src/Packages_details.txt b/doc/src/Packages_details.txt index 494f393a16..73345a2940 100644 --- a/doc/src/Packages_details.txt +++ b/doc/src/Packages_details.txt @@ -89,6 +89,7 @@ as contained in the file name. "USER-NETCDF"_#PKG-USER-NETCDF, "USER-OMP"_#PKG-USER-OMP, "USER-PHONON"_#PKG-USER-PHONON, +"USER-PTM"_#PKG-USER-PTM, "USER-QMMM"_#PKG-USER-QMMM, "USER-QTB"_#PKG-USER-QTB, "USER-QUIP"_#PKG-USER-QUIP, @@ -1744,6 +1745,25 @@ examples/USER/phonon :ul :line +USER-PTM package :link(PKG-USER-PTM),h4 + +[Contents:] + +A "compute ptm/atom"_compute_ptm.html command that calculates +local structure characterization using the Polyhedral Template +Matching methodology. + +[Author:] Peter Mahler Larsen (MIT). + +[Supporting info:] + +src/USER-PHONON: filenames -> commands +src/USER-PHONON/README +"fix phonon"_fix_phonon.html +examples/USER/phonon :ul + +:line + USER-QMMM package :link(PKG-USER-QMMM),h4 [Contents:] diff --git a/doc/src/Packages_user.txt b/doc/src/Packages_user.txt index 70ac6022b6..6d3a8f754a 100644 --- a/doc/src/Packages_user.txt +++ b/doc/src/Packages_user.txt @@ -62,6 +62,7 @@ Package, Description, Doc page, Example, Library "USER-NETCDF"_Packages_details.html#PKG-USER-NETCDF, dump output via NetCDF,"dump netcdf"_dump_netcdf.html, n/a, ext "USER-OMP"_Packages_details.html#PKG-USER-OMP, OpenMP-enabled styles,"Speed omp"_Speed_omp.html, "Benchmarks"_http://lammps.sandia.gov/bench.html, no "USER-PHONON"_Packages_details.html#PKG-USER-PHONON, phonon dynamical matrix,"fix phonon"_fix_phonon.html, USER/phonon, no +"USER-PTM"_Packages_details.html#PKG-USER-PTM, Polyhedral Template Matching,"compute ptm/atom"_compute_ptm.html, n/a, no "USER-QMMM"_Packages_details.html#PKG-USER-QMMM, QM/MM coupling,"fix qmmm"_fix_qmmm.html, USER/qmmm, ext "USER-QTB"_Packages_details.html#PKG-USER-QTB, quantum nuclear effects,"fix qtb"_fix_qtb.html "fix qbmsst"_fix_qbmsst.html, qtb, no "USER-QUIP"_Packages_details.html#PKG-USER-QUIP, QUIP/libatoms interface,"pair_style quip"_pair_quip.html, USER/quip, ext diff --git a/doc/src/compute_ptm_atom.txt b/doc/src/compute_ptm_atom.txt index c668eb7726..6fe4d012f5 100644 --- a/doc/src/compute_ptm_atom.txt +++ b/doc/src/compute_ptm_atom.txt @@ -101,7 +101,11 @@ The (qw,qx,qy,qz) parameters represent the orientation of the local structure in quaternion form. The reference coordinates for each template (from which the orientation is determined) can be found in the {ptm_constants.h} file in the PTM source directory. -[Restrictions:] none +[Restrictions:] + +This fix is part of the USER-PTM package. It is only enabled if +LAMMPS was built with that package. See the "Build +package"_Build_package.html doc page for more info. [Related commands:] diff --git a/doc/src/computes.txt b/doc/src/computes.txt index 46dd30f757..aa6cf5bb64 100644 --- a/doc/src/computes.txt +++ b/doc/src/computes.txt @@ -70,6 +70,7 @@ Computes :h1 compute_property_atom compute_property_chunk compute_property_local + compute_ptm_atom compute_rdf compute_reduce compute_rigid_local diff --git a/doc/src/lammps.book b/doc/src/lammps.book index 828863ae67..ae58e66efd 100644 --- a/doc/src/lammps.book +++ b/doc/src/lammps.book @@ -467,6 +467,7 @@ compute_pressure_uef.html compute_property_atom.html compute_property_chunk.html compute_property_local.html +compute_ptm_atom.html compute_rdf.html compute_reduce.html compute_rigid_local.html From f23b638d471e3e76f23b82a229cb9a62a8638cf3 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 27 Sep 2018 07:23:38 -0400 Subject: [PATCH 13/13] include USER-PTM into git management --- .github/CODEOWNERS | 1 + src/.gitignore | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4f561a4c19..164bc05d60 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -30,6 +30,7 @@ src/USER-MOFFF/* @hheenen src/USER-MOLFILE/* @akohlmey src/USER-NETCDF/* @pastewka src/USER-PHONON/* @lingtikong +src/USER-PTM/* @pmla src/USER-OMP/* @akohlmey src/USER-QMMM/* @akohlmey src/USER-REAXC/* @hasanmetin diff --git a/src/.gitignore b/src/.gitignore index df3a22a5cd..13a8622fe1 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -41,6 +41,11 @@ /pair_meamc.cpp /pair_meamc.h +/ptm_*.cpp +/ptm_*.h +/compute_ptm.cpp +/compute_ptm.h + /fix_qeq*.cpp /fix_qeq*.h