63

I am trying to draw an Ising model (in my case, a grid of nodes with an undirected edge between adjacent nodes on the same row or column) using TikZ. I have the grid of nodes working nicely using a foreach loop, but I am having trouble drawing the lines between nodes. The problem lies in the fact that I am getting a syntax error when I try to \draw lines between computed node names.

Here is what I have so far:

enter image description here

Here is the code I am using:


\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\scriptsize
\foreach \i in {1,...,25}
{
        \pgfmathtruncatemacro{\y}{(\i - 1) / 5};
        \pgfmathtruncatemacro{\x}{\i - 5 * \y};
        \pgfmathtruncatemacro{\label}{\x + 5 * (4 - \y)};
        \node[circle,draw=black,fill=white!80!black,minimum size=20]
        (\label) at (1.5*\x,1.5*\y) {\label};
}
% These draw commands are working as intended.
\draw (1) -- (2);
\draw (1) -- (6);
\draw (6) -- (7);
\draw (7) -- (2);
% The loop, however, is not =(
%\foreach \x in {1,...,4}
%\foreach \y in {0,...,4}
%{
%       \pgfmathtruncatemacro{\cur}{\x + 5 * \y};
%       \pgfmathtruncatemacro{\next}{\cur + 1};
%       \draw (\cur) -- (\next);
%}
\end{tikzpicture}
\end{document}

Thank you very much for your help!

4 Answers 4

75

It's possible to use a minimum code

\documentclass{minimal}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[darkstyle/.style={circle,draw,fill=gray!40,minimum size=20}]
  \foreach \x in {0,...,4}
    \foreach \y in {0,...,4} 
       {\pgfmathtruncatemacro{\label}{\x - 5 *  \y +21}
       \node [darkstyle]  (\x\y) at (1.5*\x,1.5*\y) {\label};} 

  \foreach \x in {0,...,4}
    \foreach \y [count=\yi] in {0,...,3}  
      \draw (\x\y)--(\x\yi) (\y\x)--(\yi\x) ;

\end{tikzpicture}
\end{document}  

enter image description here

Only for information you can get the grid with tkz-berge

\documentclass[border=0.25cm]{standalone}
\usepackage{tkz-berge}

\begin{document}

 \begin{tikzpicture}
      \GraphInit[vstyle=Shade]
   \grGrid[Math,RA=2,RB=2]{5}{5}
 \end{tikzpicture}

\end{document} 

enter image description here

1
  • Thanks for the solution! Your tkz-berge package is very interesting, and seems to make certain operations a lot easier. I didn't think of using (\x\y) to create the label for the node, and resorted to using a single loop instead. Jul 2, 2012 at 5:49
16

With your loop:

\foreach \x in {1,...,4}
\foreach \y in {0,...,4}
{
       \pgfmathtruncatemacro{\cur}{\x + 5* \y}
       \pgfmathtruncatemacro{\next}{\cur + 1}
       \draw (\cur) -- (\next);
}

you are actually drawing just horizontal lines. Thus, if I understood correctly the question, you need to draw vertical lines.

For simplicity I used another loop:

% Vertical connections
\foreach \start in {1,...,20}
{
    \pgfmathtruncatemacro{\down}{\start+5}
    \draw (\start) -- (\down);  
}

Here is the full code:

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{positioning}

\tikzset{darkstyle/.style={circle,draw,fill=gray!40}}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1,...,25}
{
        \pgfmathtruncatemacro{\y}{(\i - 1) / 5}
        \pgfmathtruncatemacro{\x}{\i - 5 * \y}
        \pgfmathtruncatemacro{\label}{\x + 5 * (4 - \y)}
        \node[darkstyle,minimum size=20] (\label) at (1.5*\x,1.5*\y)
        {\label};
}

% Horizontal connections

\foreach \x in {1,...,4}
\foreach \y in {0,...,4}
{
       \pgfmathtruncatemacro{\cur}{\x + 5* \y}
       \pgfmathtruncatemacro{\next}{\cur + 1}
       \draw (\cur) -- (\next);
}

% Vertical connections
\foreach \start in {1,...,20}
{
    \pgfmathtruncatemacro{\down}{\start+5}
    \draw (\start) -- (\down);  
}

\end{tikzpicture}
\end{document}

The result is:

enter image description here

5
  • Actually, my code initially was not compiling! I was getting an error about 1) not being a shape, so thought that my foreach loop had incorrect syntax. I copy-pasted the code I put up again, and now it works. I wonder what I left out in my editor... Jul 1, 2012 at 8:56
  • That's probably due to a wrong initialization of one loop: when I copied your code to test I got no errors in compiling. Jul 1, 2012 at 9:08
  • You can remove some unnecessary \pgfmathtruncatemacro for example \pgfmathtruncatemacro{\y}{(\i - 1) / 5}and you don't need to add ; at the end of \pgfmathtruncatemacro. It's not a tikz's command. Jul 1, 2012 at 9:48
  • 1
    I tried to follow the OP's MWE adding just the necessary code. Your solution is really nice and IMHO that's the one to be accepted. I'll edit my answer to remove the unnecessary ;. Thanks! Jul 1, 2012 at 9:53
  • Altermundus's answer seems to be the most comprehensive, so I will change the accepted solution accordingly. Jul 2, 2012 at 5:46
8

As this looks like a grid, you could also use one (and probably two nested foreach loops for the node generation):

\documentclass{standalone}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw[step=1.5,thick] (0,-6) grid (6,0);
\foreach \x in {0,...,4}
{   \foreach \y in {0,...,4}
    {   \pgfmathtruncatemacro{\nodelabel}{\x+\y*5+1}
        \node[circle,draw=black,fill=white!80!black,minimum size=20] (\nodelabel) at (1.5*\x,-1.5*\y) {\nodelabel};
    }
}
\end{tikzpicture}

\end{document}

enter image description here

1
  • Bien vu ! :) but you limit the action on the style of the edges with this method. Jul 1, 2012 at 9:54
1

You can let TikZ do the loops with the graphs library/\graph syntax and the subgraph Grid_n from the graphs.standard library.

If you want to alter specific edges without having to draw all of them manually, you can use the simple key and manually specify options to individual edges (or even remove them with -!-).

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs.standard}
\begin{document}
\tikz[x=+1.5cm, y=+1.5cm]
  \graph[
    grid placement,
    nodes={circle, draw=black, fill=white!80!black, minimum size=+20pt}
  ]{ subgraph Grid_n [n = 25] };
\end{document}

Output

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .