6

How could I create a lattice like this:

10 by 10 lattice

In 3D, with the ability to change the x,y and z spacing independently of each other? Any solution using any LaTeX program would be great!

I have tried to do it with asymptote but it was a resounding failure. I can't make out the structure, see any grid, nor can I adjust the values independently.

3d lattice

Here is the code I used:

size(200);
import graph3;
import grid3;

real L=10;
triple s;
currentprojection=orthographic(0.25,0.25,0.75);
surface site = scale3(0.314)*unitsphere;

for(int i=1;i<=L;++i)
{
  for(int j=1;j<=L;++j)
  {
    for(int k=1;k<=L;++k)
    {
      s=(i,j,k);
      draw(shift(s)*site,red);
    }
  }
}
4
  • +1: Looks good to me. Just change the view angle and maybe increase the spacing of the spheres a bit. Commented Dec 15, 2013 at 9:50
  • Heh, kinda the problem... changing the view angle is wonky in asymptote and I can't find a good one. I also can't get a grid connecting the points to work correctly with adjustable spacing. Commented Dec 15, 2013 at 9:51
  • You might be interested in dominique.vrel.free.fr/latex2.htm Commented Dec 15, 2013 at 16:29
  • See this question: tex.stackexchange.com/questions/97271/…
    – Alex
    Commented Dec 15, 2013 at 22:30

4 Answers 4

11

Here is an example (probably inefficient, but working great !), with Tikz :

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\def \dx{2};
\def \dy{3};
\def \dz{2};
\def \nbx{4};
\def \nby{4};
\def \nbz{4};

\foreach \x in {1,...,\nbx} {
    \foreach \y in {1,...,\nby} {
        \foreach \z in {1,...,\nbz} {
            \node at (\x*\dx,\y*\dy,\z*\dz) [circle, fill=black] {};
        }
    }
}

% z lines
\foreach \x in {1,...,\nbx} {
    \foreach \z in {1,...,\nbz}{
        \draw (\x*\dx,\dy,\z*\dz) -- ( \x*\dx,\nby*\dy,\z*\dz);
    }
}

% x lines
\foreach \y in {1,...,\nbx} {
    \foreach \z in {1,...,\nbz}{
        \draw (\dx,\y*\dy,\z*\dz) -- ( \nbx*\dx,\y*\dy,\z*\dz);
    }
}

% y lines
\foreach \x in {1,...,\nbx} {
    \foreach \y in {1,...,\nbz}{
        \draw (\x*\dx,\y*\dy,\dz) -- ( \x*\dx,\y*\dy,\nbz*\dz);
    }
}

\end{tikzpicture}
\end{document}

enter image description here

EDIT : Here is the version with arrows, it's pretty ugly :)

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\tikzset{>=latex}

\def \dx{2};
\def \dy{3};
\def \dz{2};
\def \nbx{4};
\def \nby{4};
\def \nbz{4};

\foreach \x in {1,...,\nbx} {
    \foreach \y in {1,...,\nby} {
        \foreach \z in {1,...,\nbz} {
            \node at (\x*\dx,\y*\dy,\z*\dz) [circle, fill=black] {};
        }
    }
}

% z lines
\foreach \x in {1,...,\nbx} {
    \foreach \z in {1,...,\nbz}{
        \foreach \y in {2,...,\nby}{
            \draw [->, color = red, line width = 2pt](\x*\dx,\y*\dy - \dy,\z*\dz) -- ( \x*\dx , \y*\dy, \z*\dz);
        }
    }
}

% x lines
\foreach \y in {1,...,\nbx} {
    \foreach \z in {1,...,\nbz}{
        \foreach \x in {2,...,\nbx}{
            \draw[->, color = red, line width = 2pt](\x * \dx - \dx,\y*\dy,\z*\dz) -- ( \x * \dx,\y*\dy,\z*\dz);
        }
    }
}

% y lines
\foreach \x in {1,...,\nbx} {
    \foreach \y in {1,...,\nbz}{
        \foreach \z in {2,...,\nby}{
            \draw[->, color = red, line width = 2pt](\x*\dx,\y*\dy,\z*\dz - \dz) -- ( \x*\dx,\y*\dy,\z*\dz);
        }
    }
}

\end{tikzpicture}
\end{document}

enter image description here

7
  • 1
    Your solution works great, although... if it isn't too much trouble, could you modify it to draw the lines individually? That was they can be converted to arrow to show progression from one point to the next. If its too much hassle though, don't worry! Commented Dec 15, 2013 at 11:21
  • 1
    I'm afraid my knowledge of Tikz has already reached its limit here (I'm just starting to learn it), it looks like you're expecting an use of the animate package. I hope someone will answer it, I suggest you to edit your question.
    – Thomas
    Commented Dec 15, 2013 at 11:25
  • Not an animation, something like what I use here in the third graphic: tex.stackexchange.com/questions/148510/… Commented Dec 15, 2013 at 11:36
  • OK I get it ! starting from (0,0,0) ?
    – Thomas
    Commented Dec 15, 2013 at 11:47
  • Exactly!, Its related to the Metropolis Algorithm of the Ising Model. Commented Dec 15, 2013 at 13:52
7

Using @Tomas 's code, and adding in the arrows as per a comment, I ended up with this:

enter image description here

Code: (All credits to Thomas for the base!)

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\tikzset{>=latex}

\def \dx{3};
\def \dy{3};
\def \dz{3};
\def \nbx{4};
\def \nby{4};
\def \nbz{4};

\foreach \x in {1,...,\nbx} {
    \foreach \y in {1,...,\nby} {
        \foreach \z in {1,...,\nbz} {
            \node at (\x*\dx,\y*\dy,\z*\dz) [circle, fill=red] {};
        }
    }
}

% z lines
\foreach \x in {1,...,\nbx} {
    \foreach \z in {1,...,\nbz}{
        \foreach \y in {2,...,\nby}{
            \draw [->,shorten >=0.5\dz cm,line width = 2pt]( \x*\dx , \y*\dy, \z*\dz) -- (\x*\dx,\y*\dy - \dy,\z*\dz);
        }
    }
}

% x lines
\foreach \y in {1,...,\nbx} {
    \foreach \z in {1,...,\nbz}{
        \foreach \x in {2,...,\nbx}{
            \draw[->,shorten >=0.5\dx cm, line width = 2pt](\x * \dx - \dx,\y*\dy,\z*\dz) -- ( \x * \dx,\y*\dy,\z*\dz);
        }
    }
}

% y lines
\foreach \x in {1,...,\nbx} {
    \foreach \y in {1,...,\nbz}{
        \foreach \z in {2,...,\nby}{
            \draw[->,shorten >=0.5\dy cm, line width = 2pt] ( \x*\dx,\y*\dy,\z*\dz) -- (\x*\dx,\y*\dy,\z*\dz - \dz);
        }
    }
}

\end{tikzpicture}
\end{document}
1
  • That's better ! ^_^
    – Thomas
    Commented Dec 15, 2013 at 21:29
4

You were unable to find a good viewpoint because

  1. Your spheres were far too large relative to the space between them, and
  2. Your grid was too large (specifically, too deep).

Here is a modification of your Asymptote code that does the job.

\documentclass{standalone}
\usepackage{asypictureB}
\begin{document}
\begin{asypicture}{name=3dgrid}
settings.render=8;
settings.outformat='png';
size(200);
import graph3;

int L=4;
triple s;
currentprojection=perspective(27,19,11);
real r = 0.1;
surface site = scale3(r)*unitsphere;
real dist = 1.5;

for(int i=1;i<=L;++i)
{
  for(int j=1;j<=L;++j)
  {
    for(int k=1;k<=L;++k)
    {
      s=dist*(i,j,k);
      draw(shift(s)*site,red);
      if (i < L) draw(shift(s) * (O -- (dist-r)*X), arrow=Arrow3(TeXHead2, emissive(blue)),
              p=blue+0.7pt);
      if (j < L) draw(shift(s) * (O -- (dist-r)*Y), arrow=Arrow3(TeXHead2, emissive(gray)),
              p=gray+0.7pt);
      if (k < L) draw(shift(s) * (O -- (dist-r)*Z), arrow=Arrow3(TeXHead2, emissive(green)),
              p=green+0.7pt);
    }
  }
}
\end{asypicture}
\end{document}

3d lattice

2

A somewhat more realistic solution can be achieved by using the package asymptote (as you mentioned):

\documentclass{standalone}
\usepackage{asymptote}

\begin{document}
\begin{asy}
import three;
settings.render=8;
settings.prc=false;
size(10cm);

//currentprojection=perspective((45,45,30));
currentprojection = orthographic((3,6,1));

material sphereCcolor = material(diffusepen=black, ambientpen=gray(0.1), specularpen=white);
material cylcolor = material(diffusepen=white, ambientpen=white);

real cylRadius = 0.1;
real sphereRadius = 0.25;

void drawRod(triple a, triple b) {
  surface rod = extrude(scale(cylRadius)*unitcircle, axis=length(b-a)*Z);
  triple orthovector = cross(Z, b-a);
  if (length(orthovector) > .01) {
    real angle = aCos(dot(Z, b-a) / length(b-a));
    rod = rotate(angle, orthovector) * rod;
  }
  draw(shift(a)*rod, surfacepen=cylcolor);
}

void drawCarbon(triple center) {
     draw(shift(center)*scale3(sphereRadius)*unitsphere, surfacepen=sphereCcolor);
}

triple P000 = (0,0,0);
triple P100 = 4X;
triple P010 = 4Y;
triple P001 = 4Z;
triple P011 = 4Y+4Z;
triple P101 = 4X+4Z;
triple P110 = 4X+4Y;
triple P111 = 4X+4Y+4Z;

drawRod(P000,P100);
drawRod(P000,P010);
drawRod(P000,P001);
drawRod(P010,P011);
drawRod(P001,P011);
drawRod(P100,P101);
drawRod(P001,P101);
drawRod(P100,P110);
drawRod(P010,P110);
drawRod(P011,P111);
drawRod(P101,P111);
drawRod(P110,P111);

drawCarbon(P000);
drawCarbon(P100);
drawCarbon(P010);
drawCarbon(P001);
drawCarbon(P011);
drawCarbon(P101);
drawCarbon(P110);
drawCarbon(P111);
\end{asy}
\end{document}

The lattice sites and connecting rods are in the right order with respect to each other.

Lattice unit cell

For a similar example, check out the following question: Draw realistic 3D crystal structures (diamond)

1
  • Sorry for the bad rendering. I promise you the pdf version looks better. ;)
    – strpeter
    Commented Sep 27, 2015 at 16:18

You must log in to answer this question.

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