« home

Ferroelectric Response

Creator: Stefan Bringuier

materials sciencesolid state physicsthermodynamicscetztikz

Schematic representation of ferroelectric response for BaTiO3 depicting the double-well free energy potential and polarization plots. The figure illustrates the movement of the Titanium atom within the crystal lattice as it shifts between two stable positions, corresponding to minima in the free energy curve. This Titanium displacement results in a large change in the material's polarization.


Ferroelectric Response

  Download

PNGPDF

  Code

  LaTeX

ferroelectric-response.tex (149 lines)

\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usepgfplotslibrary{groupplots}
\usetikzlibrary{fadings,shadings,calc}

% Shape rendering specs
\pgfdeclareradialshading{atomshade}{\pgfpoint{0cm}{0cm}}{%
    color(0cm)=(pgftransparent!0);
    color(0.2cm)=(pgftransparent!20);
    color(0.5cm)=(pgftransparent!50);
    color(0.7cm)=(pgftransparent!70);
    color(1cm)=(pgftransparent!100)%
}

\tikzset{
    atom/.style={circle, shading=atomshade, minimum size=0.4cm},
    bond/.style={
        line width=0.5mm,
        shading=axis,
        color=black, %Change to #1 to specify bond color
        shading angle=45
    }
}

% Define BaTiO3 (#221) unit cell projection
\newcommand{\DrawUnitCell}[1]{%
    \begin{tikzpicture}[scale=1.5]
    % Draw the unit cell
    \draw[thick] (0,0,0) -- (1,0,0) -- (1,1,0) -- (0,1,0) -- cycle; % Bottom face
    \draw[thick] (0,0,1) -- (1,0,1) -- (1,1,1) -- (0,1,1) -- cycle; % Top face
    \draw[thick] (0,0,0) -- (0,0,1);
    \draw[thick] (1,0,0) -- (1,0,1);
    \draw[thick] (1,1,0) -- (1,1,1);
    \draw[thick] (0,1,0) -- (0,1,1);

    % Draw lines connect Oxygen to Titanium
    \begin{scope}
        \ifnum \pdfstrcmp{#1}{0.5} < 0
            % Connect bottom 4 oxygens to Ti
            \draw[bond=red] (0,0.5,0.5) -- ($(0,0.5,0.5)!0.5!(0.5,#1,0.5)$);
            \draw[bond=gray] ($(0,0.5,0.5)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
            \draw[bond=red] (1,0.5,0.5) -- ($(1,0.5,0.5)!0.5!(0.5,#1,0.5)$);
            \draw[bond=gray] ($(1,0.5,0.5)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
            \draw[bond=red] (0.5,0,0.5) -- ($(0.5,0,0.5)!0.5!(0.5,#1,0.5)$);
            \draw[bond=gray] ($(0.5,0,0.5)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
            \draw[bond=red] (0.5,0.5,0) -- ($(0.5,0.5,0)!0.5!(0.5,#1,0.5)$);
            \draw[bond=gray] ($(0.5,0.5,0)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
            \draw[bond=red] (0.5,0.5,1) -- ($(0.5,0.5,1)!0.5!(0.5,#1,0.5)$);
            \draw[bond=gray] ($(0.5,0.5,1)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
        \else
            \ifnum \pdfstrcmp{#1}{0.5} > 0
                % Connect top 4 oxygens to Ti
                \draw[bond=red] (0,0.5,0.5) -- ($(0,0.5,0.5)!0.5!(0.5,#1,0.5)$);
                \draw[bond=gray] ($(0,0.5,0.5)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
                \draw[bond=red] (1,0.5,0.5) -- ($(1,0.5,0.5)!0.5!(0.5,#1,0.5)$);
                \draw[bond=gray] ($(1,0.5,0.5)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
                \draw[bond=red] (0.5,1,0.5) -- ($(0.5,1,0.5)!0.5!(0.5,#1,0.5)$);
                \draw[bond=gray] ($(0.5,1,0.5)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
                \draw[bond=red] (0.5,0.5,1) -- ($(0.5,0.5,1)!0.5!(0.5,#1,0.5)$);
                \draw[bond=gray] ($(0.5,0.5,1)!0.5!(0.5,#1,0.5)$) -- (0.5,#1,0.5);
            \else
                % Connect 8 oxygens to form octahedron
                \draw[bond=red] (0,0.5,0.5) -- (1,0.5,0.5);
                \draw[bond=red] (0.5,0,0.5) -- (0.5,1,0.5);
                \draw[bond=red] (0.5,0.5,0) -- (0.5,0.5,1);
            \fi
        \fi
    \end{scope}

    % Draw the Oxygen atoms (Red) (back perspective)
    \node[atom, anchor=center,ball color=red] at (0,0.5,0.5) {};
    \node[atom, anchor=center,ball color=red] at (0.5,0,0.5) {};
    \node[atom, anchor=center,ball color=red] at (0.5,0.5,0.0) {};

    % Draw the Barium atoms (Cyan)
    \node[atom, anchor=center,ball color=cyan] at (0,0,0) {};
    \node[atom, anchor=center,ball color=cyan] at (1,0,0) {};
    \node[atom, anchor=center,ball color=cyan] at (0,1,0) {};
    \node[atom, anchor=center,ball color=cyan] at (1,1,0) {};
    \node[atom, anchor=center,ball color=cyan] at (0,0,1) {};
    \node[atom, anchor=center,ball color=cyan] at (1,0,1) {};
    \node[atom, anchor=center,ball color=cyan] at (0,1,1) {};
    \node[atom, anchor=center,ball color=cyan] at (1,1,1) {};

    % Titanium atom (Gray)
    \node[atom, anchor=center,ball color=gray, minimum size=0.25cm] at (0.5,#1,0.5) {};

    % Draw the Oxygen atoms (red) (front perspective)
    \node[atom, anchor=center,ball color=red] at (0.5,1,0.5) {};
    \node[atom, anchor=center,ball color=red] at (1,0.5,0.5) {};
    \node[atom, anchor=center,ball color=red] at (0.5,0.5,1) {};

    \end{tikzpicture}%
}

\begin{document}
\begin{tikzpicture}[scale=0.8]
    % Define top and bottom plots
    \begin{groupplot}[
        group style={group size=1 by 2, vertical sep=0pt},
        width=10cm,
        height=6cm,
        xtick=\empty,
        ytick=\empty,
        axis lines*=box,
        enlargelimits=false,
        xmin=-2.5, xmax=2.5,
        axis line style={very thick},
    ]
        % Double-well free energy potential
        \nextgroupplot[
            ylabel={Free Energy},
            ylabel style={rotate=0},
            ymin=0, ymax=3.5,
            xlabel={}, % Remove x-axis label from top plot
            tick style={draw=none},
        ]
        \addplot[domain=-2.5:2.5, samples=100, very thick] {0.5*(\x^4-4*\x^2+4)};

        % Polarization vs. displacement
        \nextgroupplot[
            ylabel={Polarization},
            ylabel style={rotate=-90},
            ymin=-2.5, ymax=2.5,
            xlabel={Ti Displacement},
            xlabel shift={-10pt},
            xlabel near ticks,
            ylabel near ticks,
            xtick={-2.25, 2.25},
            xticklabels={negative, positive},
            tick style={draw=none},
        ]
        % Additional axes through origin
        \draw[black!50, thick] (axis cs:0,-2.475) -- (axis cs:0,2.475);
        \draw[black!50, thick] (axis cs:-2.49,0) -- (axis cs:2.49,0);

        % Polarization line
        \addplot[domain=-2.5:2.5, samples=2, blue, very thick] {\x};
    \end{groupplot}

    % Overlay the unit cells manually
    \node[anchor=center] at (1.75,3.5) {\scalebox{0.5}{\DrawUnitCell{0.3}}};
    \node[anchor=center] at (4.25,3.5) {\scalebox{0.5}{\DrawUnitCell{0.5}}};
    \node[anchor=center] at (6.75,3.5) {\scalebox{0.5}{\DrawUnitCell{0.7}}};
\end{tikzpicture}
\end{document}

  Typst

ferroelectric-response.typ (236 lines)

#import "@preview/cetz:0.3.3": canvas, draw
#import draw: rect, line, circle, content, hobby, scale

#set page(width: auto, height: auto, margin: 8pt)

#canvas({
  let arrow-style = (mark: (end: "stealth", fill: black, scale: .75))
  let plot-height = 4
  let plot-width = 10
  let y-offset = 4.65 // Reduced from 6 to bring plots closer together

  // Helper to draw axes
  let draw-axes(origin, width, height) = {
    line(
      (origin.at(0) - 0.5, origin.at(1)),
      (origin.at(0) + width, origin.at(1)),
      ..arrow-style,
      name: "x-axis",
    )
    line(
      (origin.at(0), origin.at(1) - 0.5),
      (origin.at(0), origin.at(1) + height),
      ..arrow-style,
      name: "y-axis",
    )
  }

  // Top plot: Double-well potential
  let top-origin = (-5, y-offset)
  draw-axes(top-origin, plot-width, plot-height)

  // Draw double-well potential curve using hobby spline
  hobby(
    (top-origin.at(0) + .5, top-origin.at(1) + 3.5), // start high
    (top-origin.at(0) + 1.7, top-origin.at(1) + 0.4), // left minimum
    (top-origin.at(0) + 1.8, top-origin.at(1) + 0.3), // left minimum
    (top-origin.at(0) + 5, top-origin.at(1) + 1.5), // up to middle peak
    (top-origin.at(0) + 8.2, top-origin.at(1) + 0.3), // right minimum
    (top-origin.at(0) + 8.3, top-origin.at(1) + 0.4), // right minimum
    (top-origin.at(0) + 9.5, top-origin.at(1) + 3.5), // up high again
    omega: 0,
    name: "potential-curve",
  )

  // Add "Free Energy" label
  content(
    "y-axis.mid",
    [Free Energy],
    angle: 90deg,
    anchor: "south",
    padding: (0, 0, 2pt),
  )

  // Bottom plot: Polarization vs. displacement
  let bottom-origin = (-5, 0)
  draw-axes(bottom-origin, plot-width, plot-height)

  // zero lines
  line(
    (bottom-origin.at(0), bottom-origin.at(1) + plot-height / 2),
    (bottom-origin.at(0) + plot-width, bottom-origin.at(1) + plot-height / 2),
    stroke: gray + 0.5pt,
  )
  line(
    (bottom-origin.at(0) + plot-width / 2, bottom-origin.at(1)),
    (bottom-origin.at(0) + plot-width / 2, bottom-origin.at(1) + plot-height),
    stroke: gray + 0.5pt,
  )

  // Add x-axis labels
  content(
    (bottom-origin.at(0), bottom-origin.at(1)),
    [negative],
    anchor: "north-west",
    padding: (4pt, 2pt, 0),
    name: "neg-label",
  )
  content(
    (bottom-origin.at(0) + 8.5, bottom-origin.at(1)),
    [positive],
    anchor: "north-west",
    padding: (4pt, 2pt, 0),
    name: "pos-label",
  )

  // Draw linear polarization line
  line(
    (bottom-origin.at(0), bottom-origin.at(1)),
    (bottom-origin.at(0) + plot-width, bottom-origin.at(1) + plot-height),
    stroke: blue + 1.5pt,
    name: "polarization-line",
  )

  // Add "Polarization" and "Ti Displacement" labels
  content(
    "y-axis.mid",
    [Polarization],
    angle: 90deg,
    anchor: "south",
    padding: 4pt,
  )
  content(
    "x-axis.mid",
    [Ti Displacement],
    anchor: "north",
    padding: (10pt, 0, 0),
  )

  // Helper function to draw BaTiO3 unit cell
  // TODO the face-centered oxygen atom positions need fixing and the lines overlap the atoms
  let draw-unit-cell(center-x, center-y, ti-y, cell-name) = {
    let (x, y) = (center-x, center-y)
    let z-offset = 0.3 // Consistent offset for back face
    let cube-style = (stroke: 0.7pt)

    // Draw unit cell cube with consistent offsets
    rect(
      (x - 1, y - 1),
      (x + 1, y + 1),
      ..cube-style,
      name: cell-name + "-front",
    ) // Front face
    line(
      (x - 1, y - 1),
      (x - 1 + z-offset, y - 1 + z-offset),
      ..cube-style,
      name: cell-name + "-left",
    ) // Left edge
    line(
      (x + 1, y - 1),
      (x + 1 + z-offset, y - 1 + z-offset),
      ..cube-style,
      name: cell-name + "-right",
    ) // Right edge
    line(
      (x - 1 + z-offset, y - 1 + z-offset),
      (x + 1 + z-offset, y - 1 + z-offset),
      ..cube-style,
      name: cell-name + "-back",
    ) // Back edge
    line(
      (x - 1 + z-offset, y + 1 + z-offset),
      (x + 1 + z-offset, y + 1 + z-offset),
      ..cube-style,
      name: cell-name + "-top-back",
    ) // Top back edge
    line(
      (x - 1 + z-offset, y - 1 + z-offset),
      (x - 1 + z-offset, y + 1 + z-offset),
      ..cube-style,
      name: cell-name + "-left-back",
    ) // Left back edge
    line(
      (x + 1 + z-offset, y - 1 + z-offset),
      (x + 1 + z-offset, y + 1 + z-offset),
      ..cube-style,
      name: cell-name + "-right-back",
    ) // Right back edge

    // Draw Ba atoms (all 8 corners)
    let ba-style = (stroke: none, fill: rgb("#00ffff"))
    for (pos, suffix) in (
      // Front face corners
      ((x - 1, y - 1), "front-bl"),
      ((x + 1, y - 1), "front-br"),
      ((x - 1, y + 1), "front-tl"),
      ((x + 1, y + 1), "front-tr"),
      // Back face corners
      ((x - 1 + z-offset, y - 1 + z-offset), "back-bl"),
      ((x + 1 + z-offset, y - 1 + z-offset), "back-br"),
      ((x - 1 + z-offset, y + 1 + z-offset), "back-tl"),
      ((x + 1 + z-offset, y + 1 + z-offset), "back-tr"),
    ) {
      circle(
        pos,
        radius: 0.15,
        ..ba-style,
        name: cell-name + "-ba-" + suffix,
      )
    }

    // Draw O atoms (all 6 face centers)
    let o-style = (stroke: none, fill: red)
    for (pos, suffix) in (
      // Front and back face centers
      ((x, y), "front"), // Front face center
      ((x + z-offset, y + z-offset), "back"), // Back face center
      // Face centers with consistent offsets
      ((x, y + 1), "top"), // Top face center
      ((x, y - 1), "bottom"), // Bottom face center
      ((x - 1, y), "left"), // Left face center
      ((x + 1, y), "right"), // Right face center
    ) {
      circle(
        pos,
        radius: 0.12,
        ..o-style,
        name: cell-name + "-o-" + suffix,
      )
    }

    // Draw Ti atom (center, displaced)
    let ti-style = (stroke: none, fill: gray)
    circle(
      (x + z-offset / 2, y + ti-y),
      radius: 0.1,
      ..ti-style,
      name: cell-name + "-ti",
    )

    // Draw Ti-O bonds
    let bond-style = (stroke: (thickness: 0.5pt))
    for (end-pos, suffix) in (
      ((x, y), "front"), // Front face center
      ((x + z-offset, y + z-offset), "back"), // Back face center
      ((x, y + 1), "top"), // Top face center
      ((x, y - 1), "bottom"), // Bottom face center
      ((x - 1, y), "left"), // Left face center
      ((x + 1, y), "right"), // Right face center
    ) {
      line(
        (x + z-offset / 2, y + ti-y), // Ti position
        end-pos,
        ..bond-style,
        name: cell-name + "-bond-" + suffix,
      )
    }
  }

  // Draw three unit cells with different Ti displacements
  scale(0.75)
  draw-unit-cell(-4, y-offset + 5, -0.2, "cell1")
  draw-unit-cell(0, y-offset + 5, 0, "cell2")
  draw-unit-cell(4, y-offset + 5, 0.2, "cell3")
})