From cdbbe3393384d1bf5861a9f607d7ad0cd3dd7956 Mon Sep 17 00:00:00 2001 From: Matt Bettencourt Date: Mon, 14 Aug 2023 09:36:56 +0200 Subject: [PATCH 01/43] Made check incase PyTorch didn't define the device --- python/lammps/mliap/pytorch.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/python/lammps/mliap/pytorch.py b/python/lammps/mliap/pytorch.py index 93df96d2e0..442494cb0c 100644 --- a/python/lammps/mliap/pytorch.py +++ b/python/lammps/mliap/pytorch.py @@ -18,6 +18,7 @@ import numpy as np import torch + def calc_n_params(model): """ Returns the sum of two decimal numbers in binary digits. @@ -132,22 +133,26 @@ class TorchWrapper(torch.nn.Module): descriptors = torch.as_tensor(descriptors,dtype=self.dtype, device=self.device).requires_grad_(True) elems = torch.as_tensor(elems,dtype=torch.int32, device=self.device) elems=elems-1 + device = self.device + if (use_gpu_data and device == None and str(beta.device).find('CUDA') == 1): + device = 'cuda' #Override device as it wasn't defined in the model with torch.autograd.enable_grad(): if (use_gpu_data): - energy_nn = torch.as_tensor(energy,dtype=self.dtype, device=self.device) + energy_nn = torch.as_tensor(energy,dtype=self.dtype, device=device) energy_nn[:] = self.model(descriptors, elems).flatten() else: energy_nn = self.model(descriptors, elems).flatten() energy[:] = energy_nn.detach().cpu().numpy().astype(np.float64) - + if (use_gpu_data): - beta_nn = torch.as_tensor(beta,dtype=self.dtype, device=self.device) + beta_nn = torch.as_tensor(beta,dtype=self.dtype, device=device) beta_nn[:] = torch.autograd.grad(energy_nn.sum(), descriptors)[0] else: beta_nn = torch.autograd.grad(energy_nn.sum(), descriptors)[0] beta[:] = beta_nn.detach().cpu().numpy().astype(np.float64) + class IgnoreElems(torch.nn.Module): """ A class to represent a NN model agnostic of element typing. From 7c9eda658f66e52e12ac445da74ddd4615cf9f1b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Aug 2023 03:38:05 -0400 Subject: [PATCH 02/43] fix typo --- doc/src/Howto_lammps_gui.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index 3e510bb23f..c2de63b9f6 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -286,7 +286,7 @@ General Settings: chart window will be replaced when a new snapshot image is requested, otherwise each command will create a new image window. - *Select Default Font:* Opens a font selection dialog where the type - and size for the default font (used for everthing but the editor and + and size for the default font (used for everything but the editor and log) of the application can be set. - *Select Text Font:* Opens a font selection dialog where the type and size for the text editor and log font of the application can be set. From 44f725f61fcaf2b224c2331c44c9202cd522f4f7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Aug 2023 07:11:07 -0400 Subject: [PATCH 03/43] add tooltips, add run/stop/image buttons to status bar, replace run/stop icons --- tools/lammps-gui/CMakeLists.txt | 2 +- tools/lammps-gui/emblem-default.png | Bin 3591 -> 0 bytes tools/lammps-gui/imageviewer.cpp | 20 ++++++++++++++++---- tools/lammps-gui/lammpsgui.cpp | 16 ++++++++++++++++ tools/lammps-gui/lammpsgui.qrc | 2 +- tools/lammps-gui/lammpsgui.ui | 2 +- tools/lammps-gui/process-stop.png | Bin 2287 -> 3982 bytes tools/lammps-gui/system-run.png | Bin 0 -> 4065 bytes 8 files changed, 35 insertions(+), 7 deletions(-) delete mode 100644 tools/lammps-gui/emblem-default.png create mode 100644 tools/lammps-gui/system-run.png diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt index 28169adf36..0746a4fe33 100644 --- a/tools/lammps-gui/CMakeLists.txt +++ b/tools/lammps-gui/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(lammps-gui VERSION 1.2.0 LANGUAGES CXX) +project(lammps-gui VERSION 1.2.1 LANGUAGES CXX) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) diff --git a/tools/lammps-gui/emblem-default.png b/tools/lammps-gui/emblem-default.png deleted file mode 100644 index 84fe175a0e00654a6707b2dddcbb7cb29984b816..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3591 zcmV+i4*2njP){UcJtgUBv}#&O#+9OLbdeW(kfW` zP>KhuMy*;Ot!@9P^?}m*fL5y>>rs!jN@bnJY*oBX>Hx~!1|5+3Oe3DQS3N*C1C z%u8J||7u^TqzdIll?VnZ5%88^bZP(tW8KWU&@*@%dz$_-+0oVJghbweMxQ2%`V1oz z`JWM3u$nmCe(7FH$V2nzUhKST(Q@}?4a*?Q3XXKXhM~!Bj7It~8tunqYy?H#auoYQ zDDspuQej+Jbu~s9sXfPb;&1!6M_W2h#@Mu9t{qdK+`O5p|5XBuKdG!D1drE*=N5c; z`MsW*rPbKivJ(e8{)(Ql77+GJ_QPgHdK51GHM$X0m(9n*@KRh_dn1}p{{zqN_{mi7 zVAl{-^657=CSN-51jsjtw75h0p3m+7OyjM0dl%F!!JnF*!RsyC8Bh&O_sr6u`KS{} z|6`!%KQujRX);u!a7b=kH}7^_U4I*PHEqLlJANKbBx8>p*r2XIZv+;6jubc(@|Ma_ z^_BOm`ntEddkvs+ z85tYe9v@d54{xT4|A;`tCyBp+Nc%6UzqI;;%kFjUcxxk$bnRxq4bYjk%C8 z+-=E45=jX6x*=_fVdnp{eou7bk}(&b^Y6#EV(b1Nz)&?zsMPopZd28+2Yg6 zqgA2Vm#@6`4%epL-$nOGOGe|8G3xh51Vmudn?)r3U6PrH7_vLn`zE&R{SiL8;(m8= zpls!}YrH@BmkID}<0~k7F925ruiL&WjxffS zzJu6%YA4oy=x3g?u=~Duf75^0ITN_xKH_4-<13dodYjsJ<7n4D!#&6t5h9QaBuyw+ zLMBN;e#Tl6jnD7*6yv(Nji?MX;F|Eqh_{eDw)7iBIVS>vDe1o2ss?XKAc)tGzi464 zyoA`sw3(SGt!*N#hwT4b#BEM6=BX&I#k!R*pl-$``a7<#`2;+Q-{E%pH=LEgJ3d1S zi6lLE%_TSbb|2dYRZCf(2eP7&ZC3bAFX!mr1~x0I#@zEOuf(_BzZ0Rt8pA@B+`F*4Ol$Ef&)(HfQ=wh=`e?vRLOl zPq6wOU&8&%H^L#ivVe>C7Y3Kf4i|afv;>%Z%49g^SCmzwt-o2=0@$v6b&uw`r$&*| z%smjz`W?Sy$$@*WeHQq7rtpk8YTsx( z;)!SuK7C^I-Bc{E)itVG-WMCr zzlaGbcRM_Y#3pk+Yy%ChYs0Ho%wCE0x4eupUsYx*m*T+#*KEejf;uA#(8t9UEAaLA z>}1VNC@*+bRdo}Im^K>iL-XLPm>5cV^AaEwB~FKn5tzvFa4r$5Hzprm@(>|u?3 z;*GDa#YANEyqxPK5(ynV2W^fV=*Hb^@N)B087wY`8&hn3G7t9WU&Ipak0mDAgB~G0 z!s?oY`$O%!u=Y3a#Td_6|G{N?-ZT!L&-vJ&K81a)JB8E>CLs@|q7z)hUDIqOq^@Xu z55XL`eqD`_u*eXn&Fz~o;SU3TG!AiJiP68oa%eiaF&%cxH7nd znX=!`U&u7=j{~EEP!QVlWpKI`q2Y$*4Gq@TK#v4P zYhN?IwCP54549l{i)CrrT$Cbc(?k+~KfVRu+3|5Ek`Y$?A^0 z1ol2j-%cju{S%R41dBtESt`wvj%tyhnc|ct)H!%cms97!DV>A~a=Lqw#BcXLh9_SA zA|sm6-(yznOcdBVLS+@`8|mPgvB`d>n%xg*WK;J*N3ycK8j4HOx5MJG2Q>g|nbErM z8E(T@H{XJ`zN0!=yV*%ZqLcXPE1$>j5BxYY4^?xIT6j&G8JvaQ{>~`tQ+|2Ien6E{ zKReyps(M^LloXZdB=~k*6TNPRST*Hk5g8os#n*nf3N5`&Ii456k4*IA(HB3C*G@d2 znMV_%ngP$yRg{OJ(ggYjd)0)dJ$pt12Y*gmRibS?(RM6eQ&A6xThh&pgf1at@=OF$ zA^?h!$pNg}dOJ>Z9morw%WeJhAH?zQ{aKNu!n)$0^G?p?Q81g~IM#B6?eFQg4{xBu zXKm`0xcX3MM@NcxLR@=JorDaTO-KdZYgzY#oERZq>C)!?(fw9sGU4(jY>m zm1sWNG$m1b|Lea&?5t;_#A-&R#dj(%RfK0;*-&5SKGx3U5RD_1pv>6DD@k>O?L3DV zeJ>IEUf$oC_ma^c{0W8e$@#h6uIht~F%RNKk! z(f+2?6>Qn`@^*nINwbv_Nr(hY@RG63=H{rrp7rT-l;2j(E-$UCo9pZy?O)SHJWvzVM@ySTY`1iD>Kh?GQq-`C}q}s_-JgfXSk>9kotk%eP}npCymi0Vw^MZ z4Zd|slLOu`XW?7~Yp+o@6qXerg5(OgA0ds{WKc z$~%|10X!iPFiDtF!gLW32{;WBZf3rs*{GX!nesVTfwXA$f|*KrsFZkIY_A@lK!jN$ z#j;h3ZRXS@((+{KS9Y*$k0cY(6yl>e+Wn^X!f2~@j6F7Hm`NaElTiLOU?Y%kAuBc# zK7Q!H%+E*W*rHNKrnpwR)LTL?fJ9hFL>0C$Q;H(fR7#cD8j%SlNj65N261wvg&r6@ zsU2Y=m@s-=K8_o}rv%U27q6N(3kh|=PDB>WVUXcOJVHb~hItLCIhgZ3-ZGT9yplgY zp-o0cFsdappkf9Hef4or6tNi$MiYcF(Fdpql-3mgebM{|Pqe24h)`setCheckable(true); + dossao->setToolTip("Toggle SSAO rendering"); auto *doanti = new QPushButton(QIcon(":/antialias.png"), ""); doanti->setCheckable(true); + doanti->setToolTip("Toggle anti-aliasing"); auto *dobox = new QPushButton(QIcon(":/system-box.png"), ""); dobox->setCheckable(true); + dobox->setToolTip("Toggle displaying box"); auto *doaxes = new QPushButton(QIcon(":/axes-img.png"), ""); doaxes->setCheckable(true); + doaxes->setToolTip("Toggle displaying axes"); auto *zoomin = new QPushButton(QIcon(":/gtk-zoom-in.png"), ""); + zoomin->setToolTip("Zoom in by 10 percent"); auto *zoomout = new QPushButton(QIcon(":/gtk-zoom-out.png"), ""); + zoomout->setToolTip("Zoom out by 10 percent"); auto *rotleft = new QPushButton(QIcon(":/object-rotate-left.png"), ""); + rotleft->setToolTip("Rotate left by 15 degrees"); auto *rotright = new QPushButton(QIcon(":/object-rotate-right.png"), ""); + rotright->setToolTip("Rotate right by 15 degrees"); auto *rotup = new QPushButton(QIcon(":/gtk-go-up.png"), ""); + rotup->setToolTip("Rotate up by 15 degrees"); auto *rotdown = new QPushButton(QIcon(":/gtk-go-down.png"), ""); + rotdown->setToolTip("Rotate down by 15 degrees"); auto *reset = new QPushButton(QIcon(":/gtk-zoom-fit.png"), ""); + reset->setToolTip("Reset view to defaults"); auto *combo = new QComboBox; combo->setObjectName("group"); + combo->setToolTip("Select group to display"); int ngroup = lammps->id_count("group"); char gname[64]; for (int i = 0; i < ngroup; ++i) { @@ -215,28 +227,28 @@ void ImageViewer::do_zoom_out() void ImageViewer::do_rot_left() { - vrot -= 15; + vrot -= 10; if (vrot < -180) vrot += 360; createImage(); } void ImageViewer::do_rot_right() { - vrot += 15; + vrot += 10; if (vrot > 180) vrot -= 360; createImage(); } void ImageViewer::do_rot_down() { - hrot -= 15; + hrot -= 10; if (hrot < 0) hrot += 360; createImage(); } void ImageViewer::do_rot_up() { - hrot += 15; + hrot += 10; if (hrot > 360) hrot -= 360; createImage(); } diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index d4daf198e9..e3b7979a53 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -241,7 +242,22 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) : auto pix = QPixmap(":/lammps-icon-128x128.png"); lammpsstatus->setPixmap(pix.scaled(22, 22, Qt::KeepAspectRatio)); ui->statusbar->addWidget(lammpsstatus); + lammpsstatus->setToolTip("LAMMPS instance is active"); lammpsstatus->hide(); + + auto *lammpsrun = new QPushButton(QIcon(":/system-run.png"),""); + auto *lammpsstop = new QPushButton(QIcon(":/process-stop.png"), ""); + auto *lammpsimage = new QPushButton(QIcon(":/emblem-photos.png"), ""); + lammpsrun->setToolTip("Run LAMMPS on input"); + lammpsstop->setToolTip("Stop LAMMPS"); + lammpsimage->setToolTip("Create snapshot image"); + ui->statusbar->addWidget(lammpsrun); + ui->statusbar->addWidget(lammpsstop); + ui->statusbar->addWidget(lammpsimage); + connect(lammpsrun, &QPushButton::released, this, &LammpsGui::run_buffer); + connect(lammpsstop, &QPushButton::released, this, &LammpsGui::stop_run); + connect(lammpsimage, &QPushButton::released, this, &LammpsGui::render_image); + status = new QLabel("Ready."); status->setFixedWidth(300); ui->statusbar->addWidget(status); diff --git a/tools/lammps-gui/lammpsgui.qrc b/tools/lammps-gui/lammpsgui.qrc index 88526719f0..826252ccd5 100644 --- a/tools/lammps-gui/lammpsgui.qrc +++ b/tools/lammps-gui/lammpsgui.qrc @@ -33,7 +33,7 @@ help-about.png emblem-photos.png process-stop.png - emblem-default.png + system-run.png window-close.png application-plot.png application-calc.png diff --git a/tools/lammps-gui/lammpsgui.ui b/tools/lammps-gui/lammpsgui.ui index 6bda61dbb4..635ec25db6 100644 --- a/tools/lammps-gui/lammpsgui.ui +++ b/tools/lammps-gui/lammpsgui.ui @@ -212,7 +212,7 @@ - + &Run LAMMPS diff --git a/tools/lammps-gui/process-stop.png b/tools/lammps-gui/process-stop.png index 5f547cfee3f58ad10fd7f3ae211f5502aa488576..b85df6bcabe41b94dfdcdae2293ae3f73938f58d 100644 GIT binary patch literal 3982 zcmai%cTkhd8pcBnh7JN!q=}IhNOBO64oa_5q}Px@1Oh?`HB@QRM5Rbkiu5W72r7ac z2pT|$G(kZ`2uKI1p9%=&sa%+D11 zyED+Ajn>o$31>p@W~h7POwZcE^;eN+a?VfBHUI!%qz7tufbc+6;=uz62@VKaTh&Mk{w=3YOaW&m#{ZnLLaQX zDI)WJ9`PPOu-3nt&~&}-mf_9Dhg32Pg9!4I(~zT&ZF_Yav#b(eeqEb=BV5-hI~X5^`ayGM}nlbT=0w7eZjCQH+XY1xRnG;K%QVt6Rhb zSu@6M&%_)!UyG9M9)t`p`tI3}@d&Xk$)_QBi6mCuSeVXRbV^He2CX!sH~(|#*iz_g zhrw4U+x2qCy{Sz9gHp1{u@udQ?$9TWFIQQygXSVQBe?8i4msY=J}m5M1RrI? zwPw_+#-EqC-4O07gb1$B9RK>{c2S9TyiOC`RCn;rVMaj*!e%3~2-I~Jn(kv5pTUna z*^dDkMI+z5Y!5wjl73!Ecf#q`l+pL_z1d>AP;!s?@zcXc6S`@gK%t6_==$*%jm1Jb z>T!7@i3)`h&g)SMzTe_$nOj~q32%6NAxT>8d;6S6(MAzfeoQc}ps7xYbC{Tb;Frj) zXIx4+re1<82IJVh0|BtVP+oBw?O5;rDe2y1Ch5w|G{l{15PrK#b&f&_&rzSHd{q*-SVOac7tbuT`IGO0 zFmI~Crx8m^zFs5?DSiLshfbC!LuV9TkpBAf32VWYnk(sQhZUTvAsm>mq+3LJe%m5$ z4G8C`U6Dh4xKsT_;5}{e%myI6XFB1s8f-X&{j+s^TdIZ}wF}{!X7RAP%A(@ikd>kY z(arKFF$W3dGWpPIo~0b;L42%fG%dAz4m``9RFiXe^o>k#((jy{#qbl` zWv8rLK{PIJ0m@RF`$8+62erBumBGYHi=QQ&oXf8xWOLu|AY4~d z`p!;sP{eLiB24o2GNxwd)z|u<$CI~YqyQPc0B`%5JB~G$_jYe+6?1YrG7infb*~?# zFAq}p(g)MKh2`c&B7ouZ&)3$TOn=0)B=xvp&vP<3m!m&38C}Y*R0XbCEGwl(JtBHV ze?_H8r=_f@y&+JEYgl~A8MFy%wV7(IUPvBQ zeC}f;2g*o{s4>^v3h5)mdPL1DU2Z#;fy{m$s|JIMWo%{Y8ABCjW1C?kwS>BGLOHFk?qAn}nncI9BoOgsa##wM3*E3Te!!o=Y2I=CFk5H({`|pMqEQLiDH=L!8SV zMl3UC4bz`2`_q>m*!*UfZ{fT4GxM88G>o)lH}<*qMC4MF9aS~fjuGtXHEhXmO$9K^ z(}P5nfffB}C#N#TofDFIt_me;z|Se;Dq0+QIFmYCd~%K{8N}?2a2u;xqGTOVA-jBqORzGxcff%ozCYvws3abwJ0PbE#i)MZ@89Yr6o4NghzS`>d^B30th{)}4@ z#}uD1o2nozn810(a^Ko1I)Hq?3>^IZT>o%M--`6nuW~jP#5-4aq;_QX`_93F9DPzL%5jwpf<1nO2 zCUf0@TO|Kr`T@(DCD?z3r?C!zJ_I3 zS{>bblaSmMd4R>{nO&c31BkxSC5C2Y;@K*?fJK0}6Qmti6A+ zf?7H|GlYb;vC){Ed?bDYTjRhYkvaAt|MAmt00z^mn6{9a>Lv`tN!bLATpg{ED1CtH z#`4uU6H-!ydqfvz6EX^vVVs;^DzZ`g9rVTJURI5^#h^u)O=Sg7i`wkf#;6fe#riUF zxB@ll#(u|&vyHqk&4yabslCj$CB}(iC1$h}Uv3AcB`Ajw0 zvJFD(&CH7R%A3ddgvR$dhlN=TQbGZAejL3v=CxLRsH?U}cYf!x<}ImcIFiw&I957>Reby`Varx%!Hd}X|WR7qhCRE%vw`p6kH(OGbQb&j92DQ z%Ar%B)}@_(x<|`Yk3{TYC~)gbPopB?MxUwB4R4%f^QFL1ghrUTGhu|mUBwilpj5?O zOJ6-g@@9^^Cpn_m=3vV&=)#L?+}N7xaYL=W*~79lM4nz;m}KijJ?12wfk~VI_{LBy+f-f&B>f3GIMVQt;YkuwEL7=u85}h0 zMQ%t7pzxUuvn&{}d+=fWa9sUV3hW1yRj@g?$&T<}Cz+lvDUWD4|jB`TURDR*KR0Oq? zvU|Hj5S$aV>c`EE!}@%7`;5ou7CP)re<5S2F}o4gJiRTC_ow$1mF4B}j81(&woiAm zp#cdz3jV87X6OX0N1Mt+mN*sR8}PbK^uPxgl6W)=(TWRCoDmj3VvKK?oS z>(TnDago{nnsb+BH}p%QOPvOi4fQVT>eFa^(!oI;L>ZTuX;h`$rL_H}KG~brjmT|e z$k^%>mO3kCy`ZCgf`MgIT74@v7CHd5zd}d0N%UD+Dc6SD8-}vNH#9SDXc1FF`HsaS zX2#-|7KM+yh5UEF_w)xMPSnoM?4xtSxwXb~9ZQ0rZN>99j+eZ}Uo@_?)A&e9)j}wH zmx}JAK1QY9<|&F<)(JGi&oo-@51K3_B!nCn1ZAmh97jr%{ZD_Xd~ttx@hEH(b^eVS)cAf@S=r2T!pyocSlLLd@nk&4 z#g%D{hhAQ(YFW%J<*~$h?)vVa0`Fa+4%$n5+k|x1Z4Xw8X^{d4i~557m>LWWPP+sc z!>=4szVSkPw?S#^&R6Rw3*&2DSIQ{$%{c zQ&uaWjZ3h3;P2PoWvsRh7U7R{#Udf@X9EBZg636Rw_Gm?eN zKxMse(^vc(_;=R-*^)=6s_7YU;dh{gZ=gQ{3DC!2{m~wQNMU`1FGkn`iLJX*q<-en z`LD;>%G~JRbp@b({JfE948|AdibeZkWH3mqEE?mE43_cp^i%h9^+2k^;oyM3imSrG YXm?e3rshHKSw(=pw#kh;Eti=80PVb6tN;K2 delta 2275 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 literal 0 HcmV?d00001 From 561f682afd8c845e9bf859ee3bb64e4b0d323421 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Aug 2023 08:48:31 -0400 Subject: [PATCH 04/43] support setting image dimensions, have render activity indicator --- tools/lammps-gui/emblem-photos.png | Bin 4942 -> 5406 bytes tools/lammps-gui/imageviewer.cpp | 96 ++++++++++++++++++++++------- tools/lammps-gui/imageviewer.h | 2 + tools/lammps-gui/lammpsgui.cpp | 6 +- tools/lammps-gui/preferences.h | 1 + tools/lammps-gui/system-run.png | Bin 4065 -> 4805 bytes 6 files changed, 81 insertions(+), 24 deletions(-) diff --git a/tools/lammps-gui/emblem-photos.png b/tools/lammps-gui/emblem-photos.png index d5b222fe4e0bcecf2d5f03f3e931c62a961a09b0..90e486420d74c05110a7ab903031b8c30eb4a247 100644 GIT binary patch literal 5406 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 aK_dQBO+xBdqVJ`bOiM!-TCVmo^nU>JcW?Co delta 4917 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 diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index f661db8708..b38d45fa10 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +60,30 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge QVBoxLayout *mainLayout = new QVBoxLayout; + QSettings settings; + + auto *renderstatus = new QLabel(QString()); + auto pix = QPixmap(":/emblem-photos.png"); + renderstatus->setPixmap(pix.scaled(22, 22, Qt::KeepAspectRatio)); + renderstatus->setEnabled(false); + renderstatus->setToolTip("Render status"); + settings.beginGroup("snapshot"); + auto *xval = new QSpinBox; + xval->setRange(100, 10000); + xval->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); + xval->setValue(settings.value("xsize", "800").toInt()); + xval->setObjectName("xsize"); + xval->setToolTip("Set rendered image width"); + auto *yval = new QSpinBox; + yval->setRange(100, 10000); + yval->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); + yval->setValue(settings.value("ysize", "600").toInt()); + yval->setObjectName("ysize"); + xval->setToolTip("Set rendered image height"); + settings.endGroup(); + connect(xval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size); + connect(yval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size); + auto *dossao = new QPushButton(QIcon(":/hd-img.png"), ""); dossao->setCheckable(true); dossao->setToolTip("Toggle SSAO rendering"); @@ -70,21 +96,21 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge auto *doaxes = new QPushButton(QIcon(":/axes-img.png"), ""); doaxes->setCheckable(true); doaxes->setToolTip("Toggle displaying axes"); - auto *zoomin = new QPushButton(QIcon(":/gtk-zoom-in.png"), ""); + auto *zoomin = new QPushButton(QIcon(":/gtk-zoom-in.png"), ""); zoomin->setToolTip("Zoom in by 10 percent"); - auto *zoomout = new QPushButton(QIcon(":/gtk-zoom-out.png"), ""); + auto *zoomout = new QPushButton(QIcon(":/gtk-zoom-out.png"), ""); zoomout->setToolTip("Zoom out by 10 percent"); - auto *rotleft = new QPushButton(QIcon(":/object-rotate-left.png"), ""); + auto *rotleft = new QPushButton(QIcon(":/object-rotate-left.png"), ""); rotleft->setToolTip("Rotate left by 15 degrees"); auto *rotright = new QPushButton(QIcon(":/object-rotate-right.png"), ""); rotright->setToolTip("Rotate right by 15 degrees"); - auto *rotup = new QPushButton(QIcon(":/gtk-go-up.png"), ""); + auto *rotup = new QPushButton(QIcon(":/gtk-go-up.png"), ""); rotup->setToolTip("Rotate up by 15 degrees"); - auto *rotdown = new QPushButton(QIcon(":/gtk-go-down.png"), ""); + auto *rotdown = new QPushButton(QIcon(":/gtk-go-down.png"), ""); rotdown->setToolTip("Rotate down by 15 degrees"); - auto *reset = new QPushButton(QIcon(":/gtk-zoom-fit.png"), ""); + auto *reset = new QPushButton(QIcon(":/gtk-zoom-fit.png"), ""); reset->setToolTip("Reset view to defaults"); - auto *combo = new QComboBox; + auto *combo = new QComboBox; combo->setObjectName("group"); combo->setToolTip("Select group to display"); int ngroup = lammps->id_count("group"); @@ -96,6 +122,11 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge QHBoxLayout *menuLayout = new QHBoxLayout; menuLayout->addWidget(menuBar); + menuLayout->addWidget(renderstatus); + menuLayout->addWidget(new QLabel(" Width: ")); + menuLayout->addWidget(xval); + menuLayout->addWidget(new QLabel(" Height: ")); + menuLayout->addWidget(yval); menuLayout->addWidget(dossao); menuLayout->addWidget(doanti); menuLayout->addWidget(dobox); @@ -149,6 +180,8 @@ void ImageViewer::reset_view() { QSettings settings; settings.beginGroup("snapshot"); + xsize = settings.value("xsize", "800").toInt(); + ysize = settings.value("ysize", "600").toInt(); zoom = settings.value("zoom", 1.0).toDouble(); hrot = settings.value("hrot", 60).toInt(); vrot = settings.value("vrot", 30).toInt(); @@ -163,18 +196,35 @@ void ImageViewer::reset_view() if (lo) { // grab layout manager for the top bar lo = lo->itemAt(0)->layout(); - // grab the first 4 buttons after the menu bar - auto *button = qobject_cast(lo->itemAt(1)->widget()); + + auto *field = qobject_cast(lo->itemAt(3)->widget()); + field->setValue(xsize); + field = qobject_cast(lo->itemAt(5)->widget()); + field->setValue(ysize); + + auto *button = qobject_cast(lo->itemAt(6)->widget()); button->setChecked(usessao); - button = qobject_cast(lo->itemAt(2)->widget()); + button = qobject_cast(lo->itemAt(7)->widget()); button->setChecked(antialias); - button = qobject_cast(lo->itemAt(3)->widget()); + button = qobject_cast(lo->itemAt(8)->widget()); button->setChecked(showbox); - button = qobject_cast(lo->itemAt(4)->widget()); + button = qobject_cast(lo->itemAt(9)->widget()); button->setChecked(showaxes); // grab the last entry -> group selector auto *cb = qobject_cast(lo->itemAt(lo->count() - 1)->widget()); cb->setCurrentText("all"); + this->repaint(); + } + createImage(); +} + +void ImageViewer::edit_size() +{ + QSpinBox *field = qobject_cast(sender()); + if (field->objectName() == "xsize") { + xsize = field->value(); + } else if (field->objectName() == "ysize") { + ysize = field->value(); } createImage(); } @@ -262,6 +312,11 @@ void ImageViewer::change_group(int idx) void ImageViewer::createImage() { + auto *lo = layout(); + if (lo) lo = lo->itemAt(0)->layout(); + if (lo) qobject_cast(lo->itemAt(1)->widget())->setEnabled(true); + this->repaint(); + QSettings settings; QString dumpcmd = QString("write_dump ") + group + " image "; QDir dumpdir(QDir::tempPath()); @@ -269,14 +324,14 @@ void ImageViewer::createImage() dumpcmd += dumpfile.fileName(); settings.beginGroup("snapshot"); - int aa = antialias ? 2 : 1; - int xsize = settings.value("xsize", 800).toInt() * aa; - int ysize = settings.value("ysize", 600).toInt() * aa; - int hhrot = (hrot > 180) ? 360 - hrot : hrot; + int aa = antialias ? 2 : 1; + int tmpxsize = xsize * aa; + int tmpysize = ysize * aa; + int hhrot = (hrot > 180) ? 360 - hrot : hrot; dumpcmd += blank + settings.value("color", "type").toString(); dumpcmd += blank + settings.value("diameter", "type").toString(); - dumpcmd += QString(" size ") + QString::number(xsize) + blank + QString::number(ysize); + dumpcmd += QString(" size ") + QString::number(tmpxsize) + blank + QString::number(tmpysize); dumpcmd += QString(" zoom ") + QString::number(zoom); lammps->command(dumpcmd.toLocal8Bit()); if (lammps->extract_setting("dimension") == 3) { @@ -311,13 +366,12 @@ void ImageViewer::createImage() } dumpfile.remove(); - settings.beginGroup("snapshot"); - xsize = settings.value("xsize", 800).toInt(); - ysize = settings.value("ysize", 600).toInt(); - settings.endGroup(); // scale back to achieve antialiasing image = newImage.scaled(xsize, ysize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); imageLabel->setPixmap(QPixmap::fromImage(image)); + imageLabel->adjustSize(); + if (lo) qobject_cast(lo->itemAt(1)->widget())->setEnabled(false); + this->repaint(); } void ImageViewer::saveAs() diff --git a/tools/lammps-gui/imageviewer.h b/tools/lammps-gui/imageviewer.h index b81e5b0d59..b804e5658d 100644 --- a/tools/lammps-gui/imageviewer.h +++ b/tools/lammps-gui/imageviewer.h @@ -45,6 +45,7 @@ private slots: void normalSize(); void fitToWindow(); + void edit_size(); void reset_view(); void toggle_ssao(); void toggle_anti(); @@ -86,6 +87,7 @@ private: LammpsWrapper *lammps; QString group; QString filename; + int xsize, ysize; int hrot, vrot; double zoom; bool showbox, showaxes, antialias, usessao; diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index e3b7979a53..e00a927776 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -245,8 +245,8 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) : lammpsstatus->setToolTip("LAMMPS instance is active"); lammpsstatus->hide(); - auto *lammpsrun = new QPushButton(QIcon(":/system-run.png"),""); - auto *lammpsstop = new QPushButton(QIcon(":/process-stop.png"), ""); + auto *lammpsrun = new QPushButton(QIcon(":/system-run.png"), ""); + auto *lammpsstop = new QPushButton(QIcon(":/process-stop.png"), ""); auto *lammpsimage = new QPushButton(QIcon(":/emblem-photos.png"), ""); lammpsrun->setToolTip("Run LAMMPS on input"); lammpsstop->setToolTip("Stop LAMMPS"); @@ -257,7 +257,7 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) : connect(lammpsrun, &QPushButton::released, this, &LammpsGui::run_buffer); connect(lammpsstop, &QPushButton::released, this, &LammpsGui::stop_run); connect(lammpsimage, &QPushButton::released, this, &LammpsGui::render_image); - + status = new QLabel("Ready."); status->setFixedWidth(300); ui->statusbar->addWidget(status); diff --git a/tools/lammps-gui/preferences.h b/tools/lammps-gui/preferences.h index 1aa447e7b1..919bc48798 100644 --- a/tools/lammps-gui/preferences.h +++ b/tools/lammps-gui/preferences.h @@ -34,6 +34,7 @@ private slots: public: bool need_relaunch; + private: QTabWidget *tabWidget; QDialogButtonBox *buttonBox; diff --git a/tools/lammps-gui/system-run.png b/tools/lammps-gui/system-run.png index 3aad101a211d20ef015789350dc8d8582194522f..71d0c6d73270c4ba950c66b0f45d40243890bb26 100644 GIT binary patch delta 4649 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 From ebbce58da6ebcd3a1ca8df578a3a84ff4698f7be Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Aug 2023 12:07:43 -0400 Subject: [PATCH 05/43] fix typo --- tools/lammps-gui/imageviewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index b38d45fa10..1738b9ad1f 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -79,7 +79,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge yval->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); yval->setValue(settings.value("ysize", "600").toInt()); yval->setObjectName("ysize"); - xval->setToolTip("Set rendered image height"); + yval->setToolTip("Set rendered image height"); settings.endGroup(); connect(xval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size); connect(yval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size); From 2c8a3d87a0c1c075981734a91d137833084708d6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Aug 2023 13:06:09 -0400 Subject: [PATCH 06/43] must stop running LAMMPS simulation before we can close the lammps object --- tools/lammps-gui/lammpsgui.cpp | 20 +++++++++++++++++++- tools/lammps-gui/lammpsgui.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index e00a927776..8c5886dd5e 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -296,6 +296,10 @@ void LammpsGui::new_document() current_file.clear(); ui->textEdit->document()->setPlainText(QString()); + if (lammps.is_running()) { + stop_run(); + runner->wait(); + } lammps.close(); lammpsstatus->hide(); setWindowTitle(QString("LAMMPS-GUI - *unknown*")); @@ -565,6 +569,10 @@ void LammpsGui::save_as() void LammpsGui::quit() { + if (lammps.is_running()) { + stop_run(); + runner->wait(); + } lammps.close(); lammpsstatus->hide(); lammps.finalize(); @@ -822,7 +830,7 @@ void LammpsGui::run_buffer() char *input = mystrdup(ui->textEdit->toPlainText().toStdString() + "\n"); is_running = true; - LammpsRunner *runner = new LammpsRunner(this); + runner = new LammpsRunner(this); runner->setup_run(&lammps, input); connect(runner, &LammpsRunner::resultReady, this, &LammpsGui::run_done); connect(runner, &LammpsRunner::finished, runner, &QObject::deleteLater); @@ -1051,6 +1059,11 @@ void LammpsGui::edit_variables() SetVariables vars(newvars); if (vars.exec() == QDialog::Accepted) { variables = newvars; + if (lammps.is_running()) { + stop_run(); + runner->wait(); + delete runner; + } lammps.close(); lammpsstatus->hide(); } @@ -1073,6 +1086,11 @@ void LammpsGui::preferences() (oldthreads != settings.value("nthreads", 1).toInt()) || (oldecho != settings.value("echo", 0).toInt()) || (oldcite != settings.value("cite", 0).toInt())) { + if (lammps.is_running()) { + stop_run(); + runner->wait(); + delete runner; + } lammps.close(); lammpsstatus->hide(); } diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h index 5fed14d743..a97a233883 100644 --- a/tools/lammps-gui/lammpsgui.h +++ b/tools/lammps-gui/lammpsgui.h @@ -26,6 +26,7 @@ // forward declarations class GeneralTab; +class LammpsRunner; QT_BEGIN_NAMESPACE namespace Ui { @@ -114,6 +115,7 @@ private: QList> variables; LammpsWrapper lammps; + LammpsRunner *runner; std::string plugin_path; bool is_running; std::vector lammps_args; From 462819904194c835376886a59bf575a719f49924 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Aug 2023 19:10:14 -0400 Subject: [PATCH 07/43] update todo --- tools/lammps-gui/TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index d9581e3ae6..aa720a321c 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -10,6 +10,7 @@ LAMMPS-GUI TODO list: - need to handle "label" and "jump" commands from within ? - switch processing of input to line based commands or? - switch input file editor to read-only while loop is running +- triple quoted heredocs don't work with lammps_commands_string() # Long term ideas - add feature to LAMMPS (to the LAMMPS class) to store current file name and line number, update while reading/parsing From f91dc3e68ac01ea28a3c83d66d2cef1963dc66fd Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Aug 2023 20:24:57 -0400 Subject: [PATCH 08/43] implement anti-aliasing for dump image (and dump movie) --- doc/src/dump_image.rst | 15 +++++++++++- src/dump_image.cpp | 29 ++++++++++++++++++++++ src/image.cpp | 55 +++++++++++++++++++++++++++++++++--------- src/image.h | 3 ++- 4 files changed, 89 insertions(+), 13 deletions(-) diff --git a/doc/src/dump_image.rst b/doc/src/dump_image.rst index 25d1efff7d..2aec55bb60 100644 --- a/doc/src/dump_image.rst +++ b/doc/src/dump_image.rst @@ -103,7 +103,7 @@ Syntax dump_modify dump-ID keyword values ... * these keywords apply only to the *image* and *movie* styles and are documented on this page -* keyword = *acolor* or *adiam* or *amap* or *gmap* or *backcolor* or *bcolor* or *bdiam* or *bitrate* or *boxcolor* or *color* or *framerate* or *gmap* +* keyword = *acolor* or *adiam* or *amap* or *gmap* or *backcolor* or *bcolor* or *bdiam* or *bitrate* or *boxcolor* or *color* or *framerate* or *fsaa* or *gmap* * see the :doc:`dump modify ` doc page for more general keywords .. parsed-literal:: @@ -151,6 +151,8 @@ Syntax R,G,B = red/green/blue numeric values from 0.0 to 1.0 *framerate* arg = fps fps = frames per second for movie + *fsaa* arg = yes/no + yes/no = do or do not apply anti-aliasing *gmap* args = identical to *amap* args Examples @@ -957,6 +959,17 @@ frequently. ---------- +.. versionadded:: TBD + +The *fsaa* keyword can be used with the dump image command to improve +the image quality by enabling full scene anti-aliasing. Internally the +image is rendered at twice the width and height and then scaled down by +computing the average of each 2x2 block of pixels to produce a single +pixel in the final image at the original size. This produces smoother, +less ragged edges. + +---------- + The *gmap* keyword can be used with the dump image command, with its *grid* keyword, to setup a color map. The color map is used to assign a specific RGB (red/green/blue) color value to an individual grid cell diff --git a/src/dump_image.cpp b/src/dump_image.cpp index 1ba433f93f..41d4671f95 100644 --- a/src/dump_image.cpp +++ b/src/dump_image.cpp @@ -1555,6 +1555,35 @@ int DumpImage::modify_param(int narg, char **arg) return n; } + // if antialias state changes, we need to increase the buffer space + // change the (internal) image dimensions and reset the view parameters + if (strcmp(arg[0],"fsaa") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + int aa = utils::logical(FLERR, arg[1], false, lmp); + if (image->fsaa == NO) { + if (aa == YES) { + image->width = image->width*2; + image->height = image->height*2; + // reallocate buffers to make room + image->buffers(); + } + } else { + if (aa == NO) { + image->width = image->width/2; + image->height = image->height/2; + box_bounds(); + box_center(); + view_params(); + } + } + image->fsaa = aa; + // reset size based parameters + box_bounds(); + box_center(); + view_params(); + return 2; + } + if (strcmp(arg[0],"bcolor") == 0) { if (narg < 3) error->all(FLERR,"Illegal dump_modify command"); if (atom->nbondtypes == 0) diff --git a/src/image.cpp b/src/image.cpp index 0f31ae9927..2516ae3fdc 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -55,7 +55,9 @@ enum{NO,YES}; /* ---------------------------------------------------------------------- */ -Image::Image(LAMMPS *lmp, int nmap_caller) : Pointers(lmp) +Image::Image(LAMMPS *lmp, int nmap_caller) : + Pointers(lmp), depthBuffer(nullptr), surfaceBuffer(nullptr), imageBuffer(nullptr), + depthcopy(nullptr),surfacecopy(nullptr),rgbcopy(nullptr) { MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); @@ -69,6 +71,7 @@ Image::Image(LAMMPS *lmp, int nmap_caller) : Pointers(lmp) persp = 0.0; shiny = 1.0; ssao = NO; + fsaa = NO; up[0] = 0.0; up[1] = 0.0; @@ -154,6 +157,13 @@ Image::~Image() void Image::buffers() { + memory->destroy(depthBuffer); + memory->destroy(surfaceBuffer); + memory->destroy(imageBuffer); + memory->destroy(depthcopy); + memory->destroy(surfacecopy); + memory->destroy(rgbcopy); + npixels = width * height; memory->create(depthBuffer,npixels,"image:depthBuffer"); memory->create(surfaceBuffer,2*npixels,"image:surfaceBuffer"); @@ -380,6 +390,26 @@ void Image::merge() } else { writeBuffer = imageBuffer; } + + // scale down image for antialiasing. can be done in place with simple averaging + if (fsaa) { + for (int h=0; h < height; h += 2) { + for (int w=0; w < width; w +=2) { + int idx1 = 3*height*h + 3*w; + int idx2 = 3*height*h + 3*(w+1); + int idx3 = 3*height*(h+1) + 3*w; + int idx4 = 3*height*(h+1) + 3*(w+1); + + int out = 3*(height/2)*(h/2) + 3*(w/2); + for (int i=0; i < 3; ++i) { + writeBuffer[out+i] = (unsigned char) (0.25*((int)writeBuffer[idx1+i] + +(int)writeBuffer[idx2+i] + +(int)writeBuffer[idx3+i] + +(int)writeBuffer[idx4+i])); + } + } + } + } } /* ---------------------------------------------------------------------- @@ -1037,6 +1067,7 @@ void Image::compute_SSAO() void Image::write_JPG(FILE *fp) { #ifdef LAMMPS_JPEG + int aafactor = fsaa ? 2 : 1; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer; @@ -1044,8 +1075,8 @@ void Image::write_JPG(FILE *fp) cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo,fp); - cinfo.image_width = width; - cinfo.image_height = height; + cinfo.image_width = width/aafactor; + cinfo.image_height = height/aafactor; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; @@ -1055,7 +1086,7 @@ void Image::write_JPG(FILE *fp) while (cinfo.next_scanline < cinfo.image_height) { row_pointer = (JSAMPROW) - &writeBuffer[(cinfo.image_height - 1 - cinfo.next_scanline) * 3 * width]; + &writeBuffer[(cinfo.image_height - 1 - cinfo.next_scanline) * 3 * (width/aafactor)]; jpeg_write_scanlines(&cinfo,&row_pointer,1); } @@ -1071,6 +1102,7 @@ void Image::write_JPG(FILE *fp) void Image::write_PNG(FILE *fp) { #ifdef LAMMPS_PNG + int aafactor = fsaa ? 2 : 1; png_structp png_ptr; png_infop info_ptr; @@ -1091,7 +1123,7 @@ void Image::write_PNG(FILE *fp) png_init_io(png_ptr, fp); png_set_compression_level(png_ptr,Z_BEST_COMPRESSION); - png_set_IHDR(png_ptr,info_ptr,width,height,8,PNG_COLOR_TYPE_RGB, + png_set_IHDR(png_ptr,info_ptr,width/aafactor,height/aafactor,8,PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); png_text text_ptr[2]; @@ -1111,9 +1143,9 @@ void Image::write_PNG(FILE *fp) png_set_text(png_ptr,info_ptr,text_ptr,1); png_write_info(png_ptr,info_ptr); - auto row_pointers = new png_bytep[height]; - for (int i=0; i < height; ++i) - row_pointers[i] = (png_bytep) &writeBuffer[(height-i-1)*3*width]; + auto row_pointers = new png_bytep[height/aafactor]; + for (int i=0; i < height/aafactor; ++i) + row_pointers[i] = (png_bytep) &writeBuffer[((height/aafactor)-i-1)*3*(width/aafactor)]; png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); @@ -1129,11 +1161,12 @@ void Image::write_PNG(FILE *fp) void Image::write_PPM(FILE *fp) { - fprintf(fp,"P6\n%d %d\n255\n",width,height); + int aafactor = fsaa ? 2 : 1; + fprintf(fp,"P6\n%d %d\n255\n",width/aafactor,height/aafactor); int y; - for (y = height-1; y >= 0; y--) - fwrite(&writeBuffer[y*width*3],3,width,fp); + for (y = (height/aafactor)-1; y >= 0; y--) + fwrite(&writeBuffer[y*(width/aafactor)*3],3,width/aafactor,fp); } /* ---------------------------------------------------------------------- diff --git a/src/image.h b/src/image.h index 51a0acc61c..4f87e92b67 100644 --- a/src/image.h +++ b/src/image.h @@ -28,13 +28,14 @@ class Image : protected Pointers { double zoom; // zoom factor double persp; // perspective factor double shiny; // shininess of objects + int fsaa; // antialiasing on or off int ssao; // SSAO on or off int seed; // RN seed for SSAO double ssaoint; // strength of shading from 0 to 1 double *boxcolor; // color to draw box outline with int background[3]; // RGB values of background - double ambientColor[3]; // light color settings (adjustable by caller) + double ambientColor[3]; // light color settings (adjustable by caller) double keyLightColor[3]; double fillLightColor[3]; double backLightColor[3]; From 43347b87cebb0873790e21d26b277105b523de4f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Aug 2023 00:38:46 -0400 Subject: [PATCH 09/43] also recognize integer ranges with : or * as integer --- tools/lammps-gui/highlighter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/lammps-gui/highlighter.cpp b/tools/lammps-gui/highlighter.cpp index c2afb28342..7ed4844c69 100644 --- a/tools/lammps-gui/highlighter.cpp +++ b/tools/lammps-gui/highlighter.cpp @@ -183,7 +183,7 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) } const QString number_keywords[] = { - QStringLiteral("(^|\\s+)[0-9]+"), // integer + QStringLiteral("(^|\\s+)[0-9:*]+"), // integer and integer ranges QStringLiteral("(^|\\s+)[0-9]+\\.[0-9]*[edED]?[-+]?[0-9]*"), // floating point 1 QStringLiteral("(^|\\s+)[0-9]*\\.[0-9]+[edED]?[-+]?[0-9]*"), // floating point 2 QStringLiteral("(^|\\s+)[0-9]+([edED][-+]?[0-9]+)?") // floating point 3 @@ -207,10 +207,12 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) void Highlighter::highlightBlock(const QString &text) { + // clang-format off auto style = QRegularExpression("^(fix|compute|dump|set)\\s+(\\w+)\\s+(\\S+)\\s+(\\S+)").match(text); auto force = QRegularExpression("^(atom_style|pair_style|bond_style|angle_style|dihedral_style|improper_style|kspace_style)\\s+(\\S+)").match(text); auto defs = QRegularExpression("^(group|variable)\\s+(\\S+)\\s+(\\S+)").match(text); auto undo = QRegularExpression("^(unfix|uncompute|undump)\\s+(\\w+)").match(text); + // clang-format on bool do_style = true; bool do_force = true; bool do_defs = true; From 3ac856cc922c7ae90dd04a6d6cf49286486d9477 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Aug 2023 00:39:10 -0400 Subject: [PATCH 10/43] add extract_global() and extract_atom() --- tools/lammps-gui/lammpswrapper.cpp | 26 ++++++++++++++++++++++++++ tools/lammps-gui/lammpswrapper.h | 6 ++++++ 2 files changed, 32 insertions(+) diff --git a/tools/lammps-gui/lammpswrapper.cpp b/tools/lammps-gui/lammpswrapper.cpp index ff5a4f2213..bb46d7c425 100644 --- a/tools/lammps-gui/lammpswrapper.cpp +++ b/tools/lammps-gui/lammpswrapper.cpp @@ -45,6 +45,32 @@ int LammpsWrapper::extract_setting(const char *keyword) return val; } +void *LammpsWrapper::extract_global(const char *keyword) +{ + void *val = nullptr; + if (lammps_handle) { +#if defined(LAMMPS_GUI_USE_PLUGIN) + val = ((liblammpsplugin_t *)plugin_handle)->extract_global(lammps_handle, keyword); +#else + val = lammps_extract_global(lammps_handle, keyword); +#endif + } + return val; +} + +void *LammpsWrapper::extract_atom(const char *keyword) +{ + void *val = nullptr; + if (lammps_handle) { +#if defined(LAMMPS_GUI_USE_PLUGIN) + val = ((liblammpsplugin_t *)plugin_handle)->extract_atom(lammps_handle, keyword); +#else + val = lammps_extract_atom(lammps_handle, keyword); +#endif + } + return val; +} + int LammpsWrapper::id_count(const char *keyword) { int val = 0; diff --git a/tools/lammps-gui/lammpswrapper.h b/tools/lammps-gui/lammpswrapper.h index 064e784981..555307960c 100644 --- a/tools/lammps-gui/lammpswrapper.h +++ b/tools/lammps-gui/lammpswrapper.h @@ -29,15 +29,21 @@ public: void force_timeout(); int extract_setting(const char *keyword); + void *extract_global(const char *keyword); + void *extract_atom(const char *keyword); + int id_count(const char *idtype); int id_name(const char *idtype, int idx, char *buf, int buflen); double get_thermo(const char *keyword); void *last_thermo(const char *keyword, int idx); + bool is_open() const { return lammps_handle != nullptr; } bool is_running(); + bool has_error() const; int get_last_error_message(char *errorbuf, int buflen); + bool config_accelerator(const char *package, const char *category, const char *setting) const; bool config_has_package(const char *pkg) const; bool has_gpu_device() const; From 37b0ba1d51f3e59d4b17245b7a53439879efaa47 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Aug 2023 00:40:00 -0400 Subject: [PATCH 11/43] import periodic table functions from VMD/molfile plugin --- tools/lammps-gui/imageviewer.cpp | 16 +++ tools/lammps-gui/periodic_table.h | 205 ++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100755 tools/lammps-gui/periodic_table.h diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index 1738b9ad1f..d1e3b5a445 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -38,6 +38,22 @@ #include #include +#include + +extern "C" { +#include "periodic_table.h" +static int get_pte_from_mass(double mass) +{ + int idx = 0; + for (int i = 0; i < nr_pte_entries; ++i) + if (fabs(mass - pte_mass[i]) < 0.65) idx = i; + if ((mass > 0.0) && (mass < 2.2)) idx = 1; + // discriminate between Cobalt and Nickel. The loop will detect Nickel + if ((mass < 61.24) && (mass > 58.8133)) idx = 27; + return idx; +} +} + static const QString blank(" "); ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent) : diff --git a/tools/lammps-gui/periodic_table.h b/tools/lammps-gui/periodic_table.h new file mode 100755 index 0000000000..42e56f3fdd --- /dev/null +++ b/tools/lammps-gui/periodic_table.h @@ -0,0 +1,205 @@ +/*************************************************************************** + * RCS INFORMATION: + * + * $RCSfile: periodic_table.h,v $ + * $Author: johns $ $Locker: $ $State: Exp $ + * $Revision: 1.12 $ $Date: 2009/01/21 17:45:41 $ + * + ***************************************************************************/ + +/* + * periodic table of elements and helper functions to convert + * ordinal numbers to labels and back. + * all tables and functions are declared static, so that it + * can be safely included by all plugins that may need it. + * + * 2002-2009 akohlmey@cmm.chem.upenn.edu, vmd@ks.uiuc.edu + */ + +#include +#include + +/* periodic table of elements for translation of ordinal to atom type */ +static const char *pte_label[] = { + "X", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", + "Na", "Mg", "Al", "Si", "P" , "S", "Cl", "Ar", "K", "Ca", "Sc", + "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", + "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", + "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", + "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", + "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", + "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", + "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", + "Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", + "Ds", "Rg" +}; +static const int nr_pte_entries = sizeof(pte_label) / sizeof(char *); + +/* corresponding table of masses. */ +static const double pte_mass[] = { + /* X */ 0.00000, 1.00794, 4.00260, 6.941, 9.012182, 10.811, + /* C */ 12.0107, 14.0067, 15.9994, 18.9984032, 20.1797, + /* Na */ 22.989770, 24.3050, 26.981538, 28.0855, 30.973761, + /* S */ 32.065, 35.453, 39.948, 39.0983, 40.078, 44.955910, + /* Ti */ 47.867, 50.9415, 51.9961, 54.938049, 55.845, 58.9332, + /* Ni */ 58.6934, 63.546, 65.409, 69.723, 72.64, 74.92160, + /* Se */ 78.96, 79.904, 83.798, 85.4678, 87.62, 88.90585, + /* Zr */ 91.224, 92.90638, 95.94, 98.0, 101.07, 102.90550, + /* Pd */ 106.42, 107.8682, 112.411, 114.818, 118.710, 121.760, + /* Te */ 127.60, 126.90447, 131.293, 132.90545, 137.327, + /* La */ 138.9055, 140.116, 140.90765, 144.24, 145.0, 150.36, + /* Eu */ 151.964, 157.25, 158.92534, 162.500, 164.93032, + /* Er */ 167.259, 168.93421, 173.04, 174.967, 178.49, 180.9479, + /* W */ 183.84, 186.207, 190.23, 192.217, 195.078, 196.96655, + /* Hg */ 200.59, 204.3833, 207.2, 208.98038, 209.0, 210.0, 222.0, + /* Fr */ 223.0, 226.0, 227.0, 232.0381, 231.03588, 238.02891, + /* Np */ 237.0, 244.0, 243.0, 247.0, 247.0, 251.0, 252.0, 257.0, + /* Md */ 258.0, 259.0, 262.0, 261.0, 262.0, 266.0, 264.0, 269.0, + /* Mt */ 268.0, 271.0, 272.0 +}; + +/* + * corresponding table of VDW radii. + * van der Waals radii are taken from A. Bondi, + * J. Phys. Chem., 68, 441 - 452, 1964, + * except the value for H, which is taken from R.S. Rowland & R. Taylor, + * J.Phys.Chem., 100, 7384 - 7391, 1996. Radii that are not available in + * either of these publications have RvdW = 2.00 Å. + * The radii for Ions (Na, K, Cl, Ca, Mg, and Cs are based on the CHARMM27 + * Rmin/2 parameters for (SOD, POT, CLA, CAL, MG, CES) by default. + */ +static const double pte_vdw_radius[] = { + /* X */ 1.5, 1.2, 1.4, 1.82, 2.0, 2.0, + /* C */ 1.7, 1.55, 1.52, 1.47, 1.54, + /* Na */ 1.36, 1.18, 2.0, 2.1, 1.8, + /* S */ 1.8, 2.27, 1.88, 1.76, 1.37, 2.0, + /* Ti */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Ni */ 1.63, 1.4, 1.39, 1.07, 2.0, 1.85, + /* Se */ 1.9, 1.85, 2.02, 2.0, 2.0, 2.0, + /* Zr */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Pd */ 1.63, 1.72, 1.58, 1.93, 2.17, 2.0, + /* Te */ 2.06, 1.98, 2.16, 2.1, 2.0, + /* La */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Eu */ 2.0, 2.0, 2.0, 2.0, 2.0, + /* Er */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* W */ 2.0, 2.0, 2.0, 2.0, 1.72, 1.66, + /* Hg */ 1.55, 1.96, 2.02, 2.0, 2.0, 2.0, 2.0, + /* Fr */ 2.0, 2.0, 2.0, 2.0, 2.0, 1.86, + /* Np */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Md */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Mt */ 2.0, 2.0, 2.0 +}; + +/* lookup functions */ + +static const char *get_pte_label(const int idx) +{ + if ((idx < 1) || (idx >= nr_pte_entries)) return pte_label[0]; + + return pte_label[idx]; +} + +static double get_pte_mass(const int idx) +{ + if ((idx < 1) || (idx >= nr_pte_entries)) return pte_mass[0]; + + return pte_mass[idx]; +} + +static double get_pte_vdw_radius(const int idx) +{ + if ((idx < 1) || (idx >= nr_pte_entries)) return pte_vdw_radius[0]; + +#if 1 + /* Replace with Hydrogen radius with an "all-atom" radius */ + if (idx == 1) + return 1.0; /* H */ +#else + /* Replace with old VMD atom radii values */ + switch (idx) { + case 1: return 1.0; /* H */ + case 6: return 1.5; /* C */ + case 7: return 1.4; /* N */ + case 8: return 1.3; /* O */ + case 9: return 1.2; /* F */ + case 15: return 1.5; /* P */ + case 16: return 1.9; /* S */ + } +#endif + + return pte_vdw_radius[idx]; +} + +static int get_pte_idx(const char *label) +{ + int i; + char atom[3]; + + /* zap string */ + atom[0] = (char) 0; + atom[1] = (char) 0; + atom[2] = (char) 0; + /* if we don't have a null-pointer, there must be at least two + * chars, which is all we need. we convert to the capitalization + * convention of the table above during assignment. */ + if (label != NULL) { + atom[0] = (char) toupper((int) label[0]); + atom[1] = (char) tolower((int) label[1]); + } + /* discard numbers in atom label */ + if (isdigit(atom[1])) atom[1] = (char) 0; + + for (i=0; i < nr_pte_entries; ++i) { + if ( (pte_label[i][0] == atom[0]) + && (pte_label[i][1] == atom[1]) ) return i; + } + + return 0; +} + +static int get_pte_idx_from_string(const char *label) { + int i, ind; + char atom[3]; + + if (label != NULL) { + /* zap string */ + atom[0] = atom[1] = atom[2] = '\0'; + + for (ind=0,i=0; (ind<2) && (label[i]!='\0'); i++) { + if (label[i] != ' ') { + atom[ind] = toupper(label[i]); + ind++; + } + } + + if (ind < 1) + return 0; /* no non-whitespace characters */ + + for (i=0; i < nr_pte_entries; ++i) { + if ((toupper(pte_label[i][0]) == atom[0]) && (toupper(pte_label[i][1]) == atom[1])) + return i; + } + } + + return 0; +} + +#if 0 +#include + +int main() { + int i; + + printf("Periodic table check/dump\n"); + printf(" Table contains data for %d elements\n", nr_pte_entries); + printf(" Mass table size check: %d\n", sizeof(pte_mass) / sizeof(double)); + printf(" VDW table size check: %d\n", sizeof(pte_vdw_radius) / sizeof(double)); + printf("\n"); + printf("Symbol Num Mass rVDW\n"); + for (i=0; i Date: Thu, 17 Aug 2023 00:41:30 -0400 Subject: [PATCH 12/43] color by element when units setting allows it --- tools/lammps-gui/imageviewer.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index d1e3b5a445..d7750f225d 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -333,6 +333,19 @@ void ImageViewer::createImage() if (lo) qobject_cast(lo->itemAt(1)->widget())->setEnabled(true); this->repaint(); + int ntypes = lammps->extract_setting("ntypes"); + double *masses = (double *)lammps->extract_atom("mass"); + QString units = (const char *)lammps->extract_global("units"); + QString elements = "element "; + QString adiams; + if ((units == "real") || (units == "metal")) { + for (int i = 1; i <= ntypes; ++i) { + int idx = get_pte_from_mass(masses[i]); + elements += QString(pte_label[idx]) + blank; + adiams += QString("adiam %1 %2 ").arg(i).arg(pte_vdw_radius[idx]); + } + } + QSettings settings; QString dumpcmd = QString("write_dump ") + group + " image "; QDir dumpdir(QDir::tempPath()); @@ -345,11 +358,15 @@ void ImageViewer::createImage() int tmpysize = ysize * aa; int hhrot = (hrot > 180) ? 360 - hrot : hrot; - dumpcmd += blank + settings.value("color", "type").toString(); + if (!adiams.isEmpty()) + dumpcmd += blank + "element"; + else + dumpcmd += blank + settings.value("color", "type").toString(); dumpcmd += blank + settings.value("diameter", "type").toString(); dumpcmd += QString(" size ") + QString::number(tmpxsize) + blank + QString::number(tmpysize); dumpcmd += QString(" zoom ") + QString::number(zoom); - lammps->command(dumpcmd.toLocal8Bit()); + dumpcmd += " shiny 0.5 "; + if (lammps->extract_setting("dimension") == 3) { dumpcmd += QString(" view ") + QString::number(hhrot) + blank + QString::number(vrot); } @@ -360,12 +377,13 @@ void ImageViewer::createImage() dumpcmd += QString(" box no 0.0"); if (showaxes) - dumpcmd += QString(" axes yes 0.2 0.025"); + dumpcmd += QString(" axes yes 0.5 0.025"); else dumpcmd += QString(" axes no 0.0 0.0"); dumpcmd += " modify boxcolor " + settings.value("boxcolor", "yellow").toString(); dumpcmd += " backcolor " + settings.value("background", "black").toString(); + if (!adiams.isEmpty()) dumpcmd += blank + elements + blank + adiams; settings.endGroup(); lammps->command(dumpcmd.toLocal8Bit()); From b2a8bc07a0dbbc386e9c966b6b3b451ed6f6dc93 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Aug 2023 01:20:07 -0400 Subject: [PATCH 13/43] add option to toggle between VDW style representation and licorice style --- tools/lammps-gui/imageviewer.cpp | 54 ++++++++++++++++++++++---------- tools/lammps-gui/imageviewer.h | 3 +- tools/lammps-gui/lammpsgui.qrc | 1 + tools/lammps-gui/preferences.cpp | 20 ++++++++---- 4 files changed, 55 insertions(+), 23 deletions(-) diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index d7750f225d..780af2115d 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -78,6 +78,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge QSettings settings; + vdwfactor = 0.4; auto *renderstatus = new QLabel(QString()); auto pix = QPixmap(":/emblem-photos.png"); renderstatus->setPixmap(pix.scaled(22, 22, Qt::KeepAspectRatio)); @@ -106,6 +107,9 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge auto *doanti = new QPushButton(QIcon(":/antialias.png"), ""); doanti->setCheckable(true); doanti->setToolTip("Toggle anti-aliasing"); + auto *dovdw = new QPushButton(QIcon(":/vdw-style.png"), ""); + dovdw->setCheckable(true); + dovdw->setToolTip("Toggle VDW style representation"); auto *dobox = new QPushButton(QIcon(":/system-box.png"), ""); dobox->setCheckable(true); dobox->setToolTip("Toggle displaying box"); @@ -145,6 +149,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge menuLayout->addWidget(yval); menuLayout->addWidget(dossao); menuLayout->addWidget(doanti); + menuLayout->addWidget(dovdw); menuLayout->addWidget(dobox); menuLayout->addWidget(doaxes); menuLayout->addWidget(zoomin); @@ -159,6 +164,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge connect(dossao, &QPushButton::released, this, &ImageViewer::toggle_ssao); connect(doanti, &QPushButton::released, this, &ImageViewer::toggle_anti); + connect(dovdw, &QPushButton::released, this, &ImageViewer::toggle_vdw); connect(dobox, &QPushButton::released, this, &ImageViewer::toggle_box); connect(doaxes, &QPushButton::released, this, &ImageViewer::toggle_axes); connect(zoomin, &QPushButton::released, this, &ImageViewer::do_zoom_in); @@ -178,6 +184,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge reset_view(); dobox->setChecked(showbox); + dovdw->setChecked(vdwfactor > 1.0); doaxes->setChecked(showaxes); dossao->setChecked(usessao); doanti->setChecked(antialias); @@ -201,6 +208,7 @@ void ImageViewer::reset_view() zoom = settings.value("zoom", 1.0).toDouble(); hrot = settings.value("hrot", 60).toInt(); vrot = settings.value("vrot", 30).toInt(); + vdwfactor = settings.value("vdwstyle", false).toBool() ? 1.6 : 0.5; showbox = settings.value("box", true).toBool(); showaxes = settings.value("axes", false).toBool(); usessao = settings.value("ssao", false).toBool(); @@ -223,8 +231,10 @@ void ImageViewer::reset_view() button = qobject_cast(lo->itemAt(7)->widget()); button->setChecked(antialias); button = qobject_cast(lo->itemAt(8)->widget()); - button->setChecked(showbox); + button->setChecked(vdwfactor > 1.0); button = qobject_cast(lo->itemAt(9)->widget()); + button->setChecked(showbox); + button = qobject_cast(lo->itemAt(10)->widget()); button->setChecked(showaxes); // grab the last entry -> group selector auto *cb = qobject_cast(lo->itemAt(lo->count() - 1)->widget()); @@ -261,6 +271,17 @@ void ImageViewer::toggle_anti() createImage(); } +void ImageViewer::toggle_vdw() +{ + QPushButton *button = qobject_cast(sender()); + if (vdwfactor > 1.0) + vdwfactor = 0.4; + else + vdwfactor = 1.6; + button->setChecked(vdwfactor > 1.0); + createImage(); +} + void ImageViewer::toggle_box() { QPushButton *button = qobject_cast(sender()); @@ -333,19 +354,6 @@ void ImageViewer::createImage() if (lo) qobject_cast(lo->itemAt(1)->widget())->setEnabled(true); this->repaint(); - int ntypes = lammps->extract_setting("ntypes"); - double *masses = (double *)lammps->extract_atom("mass"); - QString units = (const char *)lammps->extract_global("units"); - QString elements = "element "; - QString adiams; - if ((units == "real") || (units == "metal")) { - for (int i = 1; i <= ntypes; ++i) { - int idx = get_pte_from_mass(masses[i]); - elements += QString(pte_label[idx]) + blank; - adiams += QString("adiam %1 %2 ").arg(i).arg(pte_vdw_radius[idx]); - } - } - QSettings settings; QString dumpcmd = QString("write_dump ") + group + " image "; QDir dumpdir(QDir::tempPath()); @@ -358,6 +366,20 @@ void ImageViewer::createImage() int tmpysize = ysize * aa; int hhrot = (hrot > 180) ? 360 - hrot : hrot; + // determine elements from masses and set their covalent radii + int ntypes = lammps->extract_setting("ntypes"); + double *masses = (double *)lammps->extract_atom("mass"); + QString units = (const char *)lammps->extract_global("units"); + QString elements = "element "; + QString adiams; + if ((units == "real") || (units == "metal")) { + for (int i = 1; i <= ntypes; ++i) { + int idx = get_pte_from_mass(masses[i]); + elements += QString(pte_label[idx]) + blank; + adiams += QString("adiam %1 %2 ").arg(i).arg(vdwfactor * pte_vdw_radius[idx]); + } + } + if (!adiams.isEmpty()) dumpcmd += blank + "element"; else @@ -365,7 +387,7 @@ void ImageViewer::createImage() dumpcmd += blank + settings.value("diameter", "type").toString(); dumpcmd += QString(" size ") + QString::number(tmpxsize) + blank + QString::number(tmpysize); dumpcmd += QString(" zoom ") + QString::number(zoom); - dumpcmd += " shiny 0.5 "; + dumpcmd += " shiny 0.5 bond atom 0.4 "; if (lammps->extract_setting("dimension") == 3) { dumpcmd += QString(" view ") + QString::number(hhrot) + blank + QString::number(vrot); @@ -383,7 +405,7 @@ void ImageViewer::createImage() dumpcmd += " modify boxcolor " + settings.value("boxcolor", "yellow").toString(); dumpcmd += " backcolor " + settings.value("background", "black").toString(); - if (!adiams.isEmpty()) dumpcmd += blank + elements + blank + adiams; + if (!adiams.isEmpty()) dumpcmd += blank + elements + blank + adiams + blank; settings.endGroup(); lammps->command(dumpcmd.toLocal8Bit()); diff --git a/tools/lammps-gui/imageviewer.h b/tools/lammps-gui/imageviewer.h index b804e5658d..e5fb6c0a72 100644 --- a/tools/lammps-gui/imageviewer.h +++ b/tools/lammps-gui/imageviewer.h @@ -49,6 +49,7 @@ private slots: void reset_view(); void toggle_ssao(); void toggle_anti(); + void toggle_vdw(); void toggle_box(); void toggle_axes(); void do_zoom_in(); @@ -89,7 +90,7 @@ private: QString filename; int xsize, ysize; int hrot, vrot; - double zoom; + double zoom, vdwfactor; bool showbox, showaxes, antialias, usessao; }; #endif diff --git a/tools/lammps-gui/lammpsgui.qrc b/tools/lammps-gui/lammpsgui.qrc index 826252ccd5..d6b941b2d0 100644 --- a/tools/lammps-gui/lammpsgui.qrc +++ b/tools/lammps-gui/lammpsgui.qrc @@ -43,5 +43,6 @@ antialias.png ovito.png vmd.png + vdw-style.png diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index 4858592dc3..40bee82378 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -138,6 +138,8 @@ void Preferences::accept() if (box) settings->setValue("box", box->isChecked()); box = tabWidget->findChild("axes"); if (box) settings->setValue("axes", box->isChecked()); + box = tabWidget->findChild("vdwstyle"); + if (box) settings->setValue("vdwstyle", box->isChecked()); QComboBox *combo = tabWidget->findChild("background"); if (combo) settings->setValue("background", combo->currentText()); combo = tabWidget->findChild("boxcolor"); @@ -395,6 +397,7 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : auto *ssao = new QLabel("HQ Image mode:"); auto *bbox = new QLabel("Show Box:"); auto *axes = new QLabel("Show Axes:"); + auto *vdw = new QLabel("VDW Style:"); auto *cback = new QLabel("Background Color:"); auto *cbox = new QLabel("Box Color:"); settings->beginGroup("snapshot"); @@ -405,6 +408,7 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : auto *sval = new QCheckBox; auto *bval = new QCheckBox; auto *eval = new QCheckBox; + auto *vval = new QCheckBox; sval->setCheckState(settings->value("ssao", false).toBool() ? Qt::Checked : Qt::Unchecked); sval->setObjectName("ssao"); aval->setCheckState(settings->value("antialias", false).toBool() ? Qt::Checked : Qt::Unchecked); @@ -413,6 +417,8 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : bval->setObjectName("box"); eval->setCheckState(settings->value("axes", false).toBool() ? Qt::Checked : Qt::Unchecked); eval->setObjectName("axes"); + vval->setCheckState(settings->value("vdwstyle", false).toBool() ? Qt::Checked : Qt::Unchecked); + vval->setObjectName("vdwstyle"); auto *intval = new QIntValidator(100, 100000, this); xval->setValidator(intval); @@ -449,8 +455,9 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : grid->addWidget(ssao, 4, 0, Qt::AlignTop); grid->addWidget(bbox, 5, 0, Qt::AlignTop); grid->addWidget(axes, 6, 0, Qt::AlignTop); - grid->addWidget(cback, 7, 0, Qt::AlignTop); - grid->addWidget(cbox, 8, 0, Qt::AlignTop); + grid->addWidget(vdw, 7, 0, Qt::AlignTop); + grid->addWidget(cback, 8, 0, Qt::AlignTop); + grid->addWidget(cbox, 9, 0, Qt::AlignTop); grid->addWidget(xval, 0, 1, Qt::AlignTop); grid->addWidget(yval, 1, 1, Qt::AlignTop); grid->addWidget(zval, 2, 1, Qt::AlignTop); @@ -458,12 +465,13 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : grid->addWidget(sval, 4, 1, Qt::AlignVCenter); grid->addWidget(bval, 5, 1, Qt::AlignVCenter); grid->addWidget(eval, 6, 1, Qt::AlignVCenter); - grid->addWidget(background, 7, 1, Qt::AlignVCenter); + grid->addWidget(vval, 7, 1, Qt::AlignVCenter); + grid->addWidget(background, 8, 1, Qt::AlignVCenter); grid->addWidget(boxcolor, 8, 1, Qt::AlignVCenter); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 9, 0); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 9, 1); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), 9, 2); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 1); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), 10, 2); setLayout(grid); } From 18aa89743016c88b52816631f1a7dcbb188ee0f5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Aug 2023 01:38:34 -0400 Subject: [PATCH 14/43] fix whitespace and include missing icon --- tools/lammps-gui/CMakeLists.txt | 2 +- tools/lammps-gui/periodic_table.h | 66 +++++++++++++++--------------- tools/lammps-gui/vdw-style.png | Bin 0 -> 3742 bytes 3 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 tools/lammps-gui/vdw-style.png diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt index 0746a4fe33..eaef9bba7f 100644 --- a/tools/lammps-gui/CMakeLists.txt +++ b/tools/lammps-gui/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(lammps-gui VERSION 1.2.1 LANGUAGES CXX) +project(lammps-gui VERSION 1.2.2 LANGUAGES CXX) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) diff --git a/tools/lammps-gui/periodic_table.h b/tools/lammps-gui/periodic_table.h index 42e56f3fdd..22138c19ad 100755 --- a/tools/lammps-gui/periodic_table.h +++ b/tools/lammps-gui/periodic_table.h @@ -20,10 +20,10 @@ #include /* periodic table of elements for translation of ordinal to atom type */ -static const char *pte_label[] = { +static const char *pte_label[] = { "X", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P" , "S", "Cl", "Ar", "K", "Ca", "Sc", - "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", + "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", @@ -36,22 +36,22 @@ static const char *pte_label[] = { static const int nr_pte_entries = sizeof(pte_label) / sizeof(char *); /* corresponding table of masses. */ -static const double pte_mass[] = { - /* X */ 0.00000, 1.00794, 4.00260, 6.941, 9.012182, 10.811, - /* C */ 12.0107, 14.0067, 15.9994, 18.9984032, 20.1797, +static const double pte_mass[] = { + /* X */ 0.00000, 1.00794, 4.00260, 6.941, 9.012182, 10.811, + /* C */ 12.0107, 14.0067, 15.9994, 18.9984032, 20.1797, /* Na */ 22.989770, 24.3050, 26.981538, 28.0855, 30.973761, /* S */ 32.065, 35.453, 39.948, 39.0983, 40.078, 44.955910, /* Ti */ 47.867, 50.9415, 51.9961, 54.938049, 55.845, 58.9332, - /* Ni */ 58.6934, 63.546, 65.409, 69.723, 72.64, 74.92160, - /* Se */ 78.96, 79.904, 83.798, 85.4678, 87.62, 88.90585, + /* Ni */ 58.6934, 63.546, 65.409, 69.723, 72.64, 74.92160, + /* Se */ 78.96, 79.904, 83.798, 85.4678, 87.62, 88.90585, /* Zr */ 91.224, 92.90638, 95.94, 98.0, 101.07, 102.90550, - /* Pd */ 106.42, 107.8682, 112.411, 114.818, 118.710, 121.760, - /* Te */ 127.60, 126.90447, 131.293, 132.90545, 137.327, + /* Pd */ 106.42, 107.8682, 112.411, 114.818, 118.710, 121.760, + /* Te */ 127.60, 126.90447, 131.293, 132.90545, 137.327, /* La */ 138.9055, 140.116, 140.90765, 144.24, 145.0, 150.36, - /* Eu */ 151.964, 157.25, 158.92534, 162.500, 164.93032, + /* Eu */ 151.964, 157.25, 158.92534, 162.500, 164.93032, /* Er */ 167.259, 168.93421, 173.04, 174.967, 178.49, 180.9479, - /* W */ 183.84, 186.207, 190.23, 192.217, 195.078, 196.96655, - /* Hg */ 200.59, 204.3833, 207.2, 208.98038, 209.0, 210.0, 222.0, + /* W */ 183.84, 186.207, 190.23, 192.217, 195.078, 196.96655, + /* Hg */ 200.59, 204.3833, 207.2, 208.98038, 209.0, 210.0, 222.0, /* Fr */ 223.0, 226.0, 227.0, 232.0381, 231.03588, 238.02891, /* Np */ 237.0, 244.0, 243.0, 247.0, 247.0, 251.0, 252.0, 257.0, /* Md */ 258.0, 259.0, 262.0, 261.0, 262.0, 266.0, 264.0, 269.0, @@ -60,24 +60,24 @@ static const double pte_mass[] = { /* * corresponding table of VDW radii. - * van der Waals radii are taken from A. Bondi, - * J. Phys. Chem., 68, 441 - 452, 1964, - * except the value for H, which is taken from R.S. Rowland & R. Taylor, - * J.Phys.Chem., 100, 7384 - 7391, 1996. Radii that are not available in - * either of these publications have RvdW = 2.00 Å. - * The radii for Ions (Na, K, Cl, Ca, Mg, and Cs are based on the CHARMM27 + * van der Waals radii are taken from A. Bondi, + * J. Phys. Chem., 68, 441 - 452, 1964, + * except the value for H, which is taken from R.S. Rowland & R. Taylor, + * J.Phys.Chem., 100, 7384 - 7391, 1996. Radii that are not available in + * either of these publications have RvdW = 2.00 \AA + * The radii for Ions (Na, K, Cl, Ca, Mg, and Cs are based on the CHARMM27 * Rmin/2 parameters for (SOD, POT, CLA, CAL, MG, CES) by default. */ -static const double pte_vdw_radius[] = { - /* X */ 1.5, 1.2, 1.4, 1.82, 2.0, 2.0, - /* C */ 1.7, 1.55, 1.52, 1.47, 1.54, +static const double pte_vdw_radius[] = { + /* X */ 1.5, 1.2, 1.4, 1.82, 2.0, 2.0, + /* C */ 1.7, 1.55, 1.52, 1.47, 1.54, /* Na */ 1.36, 1.18, 2.0, 2.1, 1.8, /* S */ 1.8, 2.27, 1.88, 1.76, 1.37, 2.0, /* Ti */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, /* Ni */ 1.63, 1.4, 1.39, 1.07, 2.0, 1.85, - /* Se */ 1.9, 1.85, 2.02, 2.0, 2.0, 2.0, + /* Se */ 1.9, 1.85, 2.02, 2.0, 2.0, 2.0, /* Zr */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, - /* Pd */ 1.63, 1.72, 1.58, 1.93, 2.17, 2.0, + /* Pd */ 1.63, 1.72, 1.58, 1.93, 2.17, 2.0, /* Te */ 2.06, 1.98, 2.16, 2.1, 2.0, /* La */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, /* Eu */ 2.0, 2.0, 2.0, 2.0, 2.0, @@ -123,7 +123,7 @@ static double get_pte_vdw_radius(const int idx) case 8: return 1.3; /* O */ case 9: return 1.2; /* F */ case 15: return 1.5; /* P */ - case 16: return 1.9; /* S */ + case 16: return 1.9; /* S */ } #endif @@ -134,13 +134,13 @@ static int get_pte_idx(const char *label) { int i; char atom[3]; - + /* zap string */ atom[0] = (char) 0; atom[1] = (char) 0; atom[2] = (char) 0; - /* if we don't have a null-pointer, there must be at least two - * chars, which is all we need. we convert to the capitalization + /* if we don't have a null-pointer, there must be at least two + * chars, which is all we need. we convert to the capitalization * convention of the table above during assignment. */ if (label != NULL) { atom[0] = (char) toupper((int) label[0]); @@ -148,12 +148,12 @@ static int get_pte_idx(const char *label) } /* discard numbers in atom label */ if (isdigit(atom[1])) atom[1] = (char) 0; - + for (i=0; i < nr_pte_entries; ++i) { if ( (pte_label[i][0] == atom[0]) && (pte_label[i][1] == atom[1]) ) return i; } - + return 0; } @@ -174,12 +174,12 @@ static int get_pte_idx_from_string(const char *label) { if (ind < 1) return 0; /* no non-whitespace characters */ - + for (i=0; i < nr_pte_entries; ++i) { - if ((toupper(pte_label[i][0]) == atom[0]) && (toupper(pte_label[i][1]) == atom[1])) + if ((toupper(pte_label[i][0]) == atom[0]) && (toupper(pte_label[i][1]) == atom[1])) return i; } - } + } return 0; } @@ -199,7 +199,7 @@ int main() { for (i=0; iO=6^j-x- zqy^!CG*OTyT?CQd1!)(L-&xTtXI z`;tOdb3W03-UEDCi7^8J*phWM)J$9^22z5^CO>brt2XU_X{ak2D8)Y(jaC>AM+dZ0 zkReco1i5TOn1E!fJjUypoFgj1Fri?%Duris#@BktQ?@0hKSo8q^ueW_r#zz%g@+9v zI&5;iGVmaMJ|{AL10|`HK`~R==Hv7rm=#lY7Cv7NR-djw@YX zR?(TcF;XF4(?;XEE7Zf98cV%8d2iXkJUmo_yd9!0H*W@of!0R3UdQErjC<0ZT3Nd| zYsTpKcS7H0_E>e0xs3IJHBVzbFn_j2%KJO$X&7ep%DRRY$Ch4-V1n$Eqzw~Xr}K-B zuEP1IE%k9h^isl3&{$06@%~!970LE(=4DuxEBy077$m-f8qw2pft0%OYms%3hGmLp z7<+KIzAe&;6(%P z-_2B*&jN#R6oJ2OikwG0y&^Gf!VCue3J_4}DsN;{t@mu(8tF0%4GXB5&VmD7RaJJD&DvqKT zP^{m1$|~pfMnPh6VTcGr+gW>VNb2sC3U-s--|G&sqh_cqVWm_M$B~!4WxaQOGrK!Z zcZ6atG_fnbhsIc!hOH3Eyx4~<2NEfbUNc%kx7V8cuh?n|xZZ^AyJIpN=ZyQ`DH=xn zoLHW2Kc(^v^E@z6l5G{ZLzmZPc2k93U|9BofaRvyWWy8U;)+(${jiT{7H%y}K1rG5 zn-2oTk|VZ#=`VAnA1Xy$yGUD0%Pe5+8FUMfqYs4OI(>S>AZL=nUM)2j-M(yt;pQ^8 za&pFeps%E9WnnF};a$2(s`Nw3+RAFlq1bv-4Nbm3J%r`VO;H$~GJRwL+M4%1!~584 zXW7;1;+NE4SFe3;YIyH<*zrwhmjbV6jR~;BboBm2M(cR(7cwZ z2w6K z4V{lz1xRp!cR;5?ytZZw+RjhrV(^3^P$QmP5u(?7VHbPhJZB zdmGrMWkQcrj~5F61{g6&we;Nxm)LY9VwBl{lE77OKwHnYx?*4kTxXZ^(CI_T&ofym z7e`7HG?ozNJUYyt{P&g0TX+FFYTf|Gz(*?MY^QSXi9fPLlk%bXnik4u+b$bsTF$Vr z0ry$2>$IKpO_x&-+*#!?N_OXH!}<5A!~*nN8R!NV;McSxQ?NE_&6|T6t&YIBJVgGG z7R0B-e+LCk-v_Ql`eWxGaO&LX6K8zmz|o;D__>bbTO~pkG~flc0ods3^EI)nWV*dx}|@#+Hv; zP+V{n;13Hkext&lRUt7yl?^cK<-7gr` zO3F&^L}0*-1Ki~_*=9MlA@uH59i!*0o(yTSiM}6wt8P5P7TitbG(%fZvwTlmYgk$% z(Hwz=qAz*HU_dq-vkR*0uWp0Ku}RDa8w-U+#YOwqsEIDN5!ewzHyhGgD#17}m_OeD zMZ3yZT&TF*klb)PV8ld_ zg#J`x3f_MEYh+4W&rpwZM-1aN!_z(33-B%u332o&_WpQ#tWSDT!r+q2q?!xNwCLz6 z87z_25Es0D1{kA$mulfN6)Ux-&1~~hRmD=U>Fo6)vj}(k@M{IF_NbX#&bWx|#q7Y0 zEY{Qx;?0wz}1& zK;emBz$Fhx7G9vgHC2xAnHtM^5H!mPY|A2K$=R~y1HXpcZ5!<;h%AT3W)@-?ge+`F@jiavsd9C3X< zy=n`hZV5_<9+oltvKCWH|M_Gjc@lyJ<|>ko2=Dt4T~h;RRSu&4h{>` z%BxSC{Vo^tl!rP~cL#Qk4c^u5Q$2;zsTuJhfg1$#bpFEQWa?UC z_Gw0cVtES)BZ7`Rg!V}?QCaHOw9Y;cnu-cF_Mi8$+cnr;ElJh&u!$F!cC`&%=EKz4 zEk~3zG5!R6oTGy(Gcw`yrL8n+Y*g;Gys&FM4qXza?AaVyhgpfw>sfz@JwbLgX>`2{ zJ-*>yrBb^c@pI5KIAhLI)WE89S}cu^sxFOnWuyQlgQ*9xbIBj%i6n;CB?Ly387TM{ zmlx9pN~F1bn(QW7+OGm?as9mIFN+TyyD|k82)Nl~+)Te?IB&le1V}Bh}*&*Vw5uSHdwoPA@Ra zDYws^s?qWA!4d9KX#_o%-R>wkcf5Q(*NP{i=`{s;0dFV{`M8VO2amoMnjUy^DnYkt z9B4HOq@**JCESMDy}&?yU|3fDV+hZ|yTTZ#bX6PdMAPHDQma(p^)`#3pduLkJ+Rjxu&ZedKG{rA^~|(ACByWd8@`x$4n?1gD-yn%=DrTzM1n6-+VLa+WDy7@X(Un_DQ|+jj6x`)JN1SAQ93CS!r2>iR>km>}3>E=?~ES?DF=10UjhrSEqpg15O-}CI}^z zEE0uO`~!IHk}FRD`QI%WxH=F$eTV=TUtcl`4*$o?l|pnNd3caKePl@9&T#iXB|dNi zZL9%YRt5=IZm#0{*YS_p|M-)X Date: Thu, 17 Aug 2023 02:23:00 -0400 Subject: [PATCH 15/43] use counter so that widgets are properly assigned to their grid slots --- tools/lammps-gui/preferences.cpp | 47 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index 40bee82378..7ce80261a9 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -448,30 +448,31 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : boxcolor->setCurrentText(settings->value("boxcolor", "yellow").toString()); settings->endGroup(); - grid->addWidget(xsize, 0, 0, Qt::AlignTop); - grid->addWidget(ysize, 1, 0, Qt::AlignTop); - grid->addWidget(zoom, 2, 0, Qt::AlignTop); - grid->addWidget(anti, 3, 0, Qt::AlignTop); - grid->addWidget(ssao, 4, 0, Qt::AlignTop); - grid->addWidget(bbox, 5, 0, Qt::AlignTop); - grid->addWidget(axes, 6, 0, Qt::AlignTop); - grid->addWidget(vdw, 7, 0, Qt::AlignTop); - grid->addWidget(cback, 8, 0, Qt::AlignTop); - grid->addWidget(cbox, 9, 0, Qt::AlignTop); - grid->addWidget(xval, 0, 1, Qt::AlignTop); - grid->addWidget(yval, 1, 1, Qt::AlignTop); - grid->addWidget(zval, 2, 1, Qt::AlignTop); - grid->addWidget(aval, 3, 1, Qt::AlignTop); - grid->addWidget(sval, 4, 1, Qt::AlignVCenter); - grid->addWidget(bval, 5, 1, Qt::AlignVCenter); - grid->addWidget(eval, 6, 1, Qt::AlignVCenter); - grid->addWidget(vval, 7, 1, Qt::AlignVCenter); - grid->addWidget(background, 8, 1, Qt::AlignVCenter); - grid->addWidget(boxcolor, 8, 1, Qt::AlignVCenter); + int i = 0; + grid->addWidget(xsize, i, 0, Qt::AlignTop); + grid->addWidget(xval, i++, 1, Qt::AlignTop); + grid->addWidget(ysize, i, 0, Qt::AlignTop); + grid->addWidget(yval, i++, 1, Qt::AlignTop); + grid->addWidget(zoom, i, 0, Qt::AlignTop); + grid->addWidget(zval, i++, 1, Qt::AlignTop); + grid->addWidget(anti, i, 0, Qt::AlignTop); + grid->addWidget(aval, i++, 1, Qt::AlignTop); + grid->addWidget(ssao, i, 0, Qt::AlignTop); + grid->addWidget(sval, i++, 1, Qt::AlignVCenter); + grid->addWidget(bbox, i, 0, Qt::AlignTop); + grid->addWidget(bval, i++, 1, Qt::AlignVCenter); + grid->addWidget(axes, i, 0, Qt::AlignTop); + grid->addWidget(eval, i++, 1, Qt::AlignVCenter); + grid->addWidget(vdw, i, 0, Qt::AlignTop); + grid->addWidget(vval, i++, 1, Qt::AlignVCenter); + grid->addWidget(cback, i, 0, Qt::AlignTop); + grid->addWidget(background, i++, 1, Qt::AlignVCenter); + grid->addWidget(cbox, i, 0, Qt::AlignTop); + grid->addWidget(boxcolor, i++, 1, Qt::AlignVCenter); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 1); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), 10, 2); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 0); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 1); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), i, 2); setLayout(grid); } From 4ec5b5776cc487088efdf0b47aaecb6b0b056696 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Aug 2023 02:25:13 -0400 Subject: [PATCH 16/43] fix permissions --- tools/lammps-gui/periodic_table.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tools/lammps-gui/periodic_table.h diff --git a/tools/lammps-gui/periodic_table.h b/tools/lammps-gui/periodic_table.h old mode 100755 new mode 100644 From 6e2a65c4c5cccf0d6fbc08f09f749f5a767917ad Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Aug 2023 05:22:57 -0400 Subject: [PATCH 17/43] update docs for LAMMPS GUI --- doc/src/Howto_lammps_gui.rst | 105 ++++++++++++++--------- doc/src/JPG/lammps-gui-image.png | Bin 83305 -> 125560 bytes doc/src/JPG/lammps-gui-main.png | Bin 91027 -> 93426 bytes doc/src/JPG/lammps-gui-prefs-general.png | Bin 53003 -> 68120 bytes doc/src/JPG/lammps-gui-running.png | Bin 32750 -> 21391 bytes 5 files changed, 63 insertions(+), 42 deletions(-) diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index c2de63b9f6..f7d4cffe13 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -65,12 +65,13 @@ Running LAMMPS ^^^^^^^^^^^^^^ From within the LAMMPS GUI main window LAMMPS can be started either from -the ``Run`` menu or by the hotkey `Ctrl-Enter` (`Command-Enter` on -macOS). LAMMPS is running in a separate thread, so the GUI will stay -responsive and thus is capable to interact with the calculation and -access its data. It is important to note, that LAMMPS is using the -contents of the input buffer for the run, **not** the file it was read -from. If there are unsaved changes in the buffer, they *will* be used. +the ``Run`` menu, by the hotkey `Ctrl-Enter` (`Command-Enter` on macOS), +or by clicking on the green button in the status bar. LAMMPS runs in a +separate thread, so the GUI stays responsive and thus it is able to +interact with the calculation and access its data. It is important to +note, that LAMMPS is using the contents of the input buffer for the run, +**not** the file it was read from. If there are unsaved changes in the +buffer, they *will* be used. .. image:: JPG/lammps-gui-running.png :align: center @@ -82,48 +83,59 @@ contain the selected number of threads, if thread-parallel acceleration was selected in the ``Preferences`` dialog. On the right side, a progress bar is shown that displays the estimated progress on the current :doc:`run command `. Additionally, two windows will open: -the log window with the captured screen output and the chart window -with a line graph created from the thermodynamic output of the run. +the log window with the captured screen output and the chart window with +a line graph created from the thermodynamic output of the run. The run can be stopped cleanly by using either the ``Stop LAMMPS`` entry -in the ``Run`` menu or with the hotkey `Ctrl-/` (`Command-/` on macOS). -This will cause that the running LAMMPS process will complete the -current iteration and then stop. This is equivalent to the command -`timer timeout 0 ` and implemented by calling the -:cpp:func:`lammps_force_timeout()` function of the LAMMPS C-library -interface. +in the ``Run`` menu, the hotkey `Ctrl-/` (`Command-/` on macOS), or +clicking on the red button in the status bar. This will cause that the +running LAMMPS process will complete the current iteration and then +stop. This is equivalent to the command `timer timeout 0 ` and +implemented by calling the :cpp:func:`lammps_force_timeout()` function +of the LAMMPS C-library interface. Viewing Snapshot Images ^^^^^^^^^^^^^^^^^^^^^^^ -By selecting the ``View Image`` entry in the ``Run`` menu or by hitting -the `Ctrl-I` (`Command-I` on macOS) hotkey, LAMMPS gui will issue a +By selecting the ``View Image`` entry in the ``Run`` menu, by hitting +the `Ctrl-I` (`Command-I` on macOS) hotkey or by clicking on the +"palette" button in the status bar, LAMMPS GUI will issue a :doc:`write_dump image ` command and read the resulting -snapshot image into an image viewer window. +snapshot image into an image viewer window. When possible, LAMMPS +GUI will try to detect which elements the atoms correspond to (via +their mass) and then colorize them accordingly. Otherwise just some +predefined sequence of colors are assigned to different atom types. .. image:: JPG/lammps-gui-image.png :align: center :scale: 50% -The image size, some default image quality settings, and some colors -can be changed in the ``Preferences`` dialog window. From the image -viewer window further adjustments can be made: high-quality rendering, -anti-aliasing, display of box or axes, zoom factor. The the image can -be rotated horizontally and vertically and it is possible to only -display the atoms within a predefined group (default is "all"). -After each change, the image is rendered again and the display updated. +The default image size, some default image quality settings, the view +style and some colors can be changed in the ``Preferences`` dialog +window. From the image viewer window further adjustments can be made: +actual image size, high-quality rendering, anti-aliasing, view style, +display of box or axes, zoom factor. The the image can be rotated +horizontally and vertically and it is possible to only display the atoms +within a predefined group (default is "all"). After each change, the +image is rendered again and the display updated. The small palette icon +on the top left will be colored while LAMMPS is running to render the +image and it will be grayed out again, when it is done. When there are +many items to show and high quality images with anti-aliasing are +requested, re-rendering can take several seconds. From the ``File`` +menu, the shown image can be saved to a file permanently or copied into +the cut-n-paste buffer for pasting into another application. Editor Functions ^^^^^^^^^^^^^^^^ -The editor has the usual functionality that similar programs have: text -selection via mouse or with cursor moves while holding the Shift key, -Cut, Copy, Paste, Undo, Redo. All of these editing functions are available -via hotkeys. When trying to exit the editor with a modified buffer, a -dialog will pop up asking whether to cancel the quit, or don't save or -save the buffer's contents to a file. +The editor has most the usual functionality that similar programs have: +text selection via mouse or with cursor moves while holding the Shift +key, Cut, Copy, Paste, Undo, Redo. All of these editing functions are +available via hotkeys. When trying to exit the editor with a modified +buffer, a dialog will pop up asking whether to cancel the quit, or don't +save or save the buffer's contents to a file. Context Specific Help ^^^^^^^^^^^^^^^^^^^^^ @@ -285,6 +297,13 @@ General Settings: - *Replace image window on new render:* when checked, an existing chart window will be replaced when a new snapshot image is requested, otherwise each command will create a new image window. +- *Path to LAMMPS Shared Library File:* this options is only available + when LAMMPS GUI was compiled to load the LAMMPS library at run time + instead of being linked to it directly. With the ``Browse..`` button + or by changing the text, a different shared library file with a + different compilation of LAMMPS with different settings or from a + different version can be loaded. After this setting was changed, + LAMMPS GUI needs to be re-launched. - *Select Default Font:* Opens a font selection dialog where the type and size for the default font (used for everything but the editor and log) of the application can be set. @@ -294,10 +313,10 @@ General Settings: Accelerators: ^^^^^^^^^^^^^ -This tab enables to select accelerator settings and is equivalent to -using the `-suffix` and `-package` flags on the command line. Only -settings supported by the LAMMPS library and local hardware are -available. The `Number of threads` field allows to set the maximum +This tab enables to select which accelerator package is used and is +equivalent to using the `-suffix` and `-package` flags on the command +line. Only settings supported by the LAMMPS library and local hardware +are available. The `Number of threads` field allows to set the maximum number of threads for the accelerator packages that use threads. Snapshot Image: @@ -306,14 +325,16 @@ Snapshot Image: This tab allows to set some defaults for the snapshot images displayed in the ``Image Viewer`` window, like its dimensions and the zoom factor applied. The *Antialias* switch requests to render images with twice -the number of pixels for width and height and then uses a bi-cubic -scaling algorithm to rescale them back to the requested size. This -produces higher quality images with smoother edges at the expense of -requiring more CPU time to render the image. The *HQ Image mode* option -turns on using a screen space ambient occlusion mode (SSAO) when -rendering images. This is also more time consuming, but produces a more -'spatial' representation of the system. Finally there are a couple of -drop down lists to select the background and box color. +the number of pixels for width and height and then smoothly scales the +image back to the requested size. This produces higher quality images +with smoother edges at the expense of requiring more CPU time to render +the image. The *HQ Image mode* option turns on using a screen space +ambient occlusion mode (SSAO) when rendering images. This is also more +time consuming, but produces a more 'spatial' representation of the +system. The *VDW Style* checkbox selects whether atoms are represented +by space filling spheres when checked or by smaller spheres and stick. +Finally there are a couple of drop down lists to select the background +and box color. Hotkeys diff --git a/doc/src/JPG/lammps-gui-image.png b/doc/src/JPG/lammps-gui-image.png index 34acdf12aa57b61d3467222801bbb1d1ed89ae0b..b383e914a523f814dbc93e22293901601e590361 100644 GIT binary patch literal 125560 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%0A#;A6J+1Yyvn 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