4

I frequently have to describe a sequence of materials in a layer stack such as the following:

Ta/Cu/Ta/Cu/Co−Fe−B/MgO/Co−Fe−B/Ta/Ru/Au

The dash indicates an alloy of unspecified composition. My question is how to properly typeset this in LaTeX.

My MWE is

\documentclass{article}

\usepackage{lipsum}
\usepackage{mhchem}

\begin{document}
\lipsum[1]

The layer stack consist of \ce{Ta}/\ce{Cu}/\ce{Ta}/\ce{Cu}/\ce{Co-Fe-B}/\ce{MgO}/\ce{Co-Fe-B}/\ce{Ta}/\ce{Ru}/\ce{Au} and all layers are sputtered in a bla bla bla

Co-Fe
\end{document}

layer stack

However, there are several things wrong with this.

  1. No line break inserted after one of the slashes
  2. The dash becomes a bond (an em dash, I believe)
  3. The frequent use of \ce looks awkward and the code is close to be unreadable.

Is there a better way to do this (with mhchem)? Please note, that the use of the dashes as well as the slashes is suggested by most publishers (in our field of research) and should not be replaced by other symbols.

  • You can use \slash instead of / if you want to allow a linebreak after a slash. If you write \ce{Co}-\ce{Fe}-\ce{B} you can avoid the bond problem (but of course you'll have even more \ces). – clemens Sep 18 '14 at 22:06
2

Before you scroll down to my code, please notice that just because this code works does not mean that it is a good way to do so.

In general, there is a data structure called "comma list". Comma list plays a role in LaTeX-programming. For example while using geometry we may say \usepackage[top=2cm,left=3cm]{geometry}. In this case, top=2cm,left=3cm is a comma list that contains two items: top=2cm and left=3cm. (They are separated by comma, hence the name.) (And then top=2cm is interpreted as a key-value pair: top the key and 2cm the value.)

Similarly, your notation is indeed a "nested comma list". The outer level is called "stack" with / being its separator. The inner level is called "layer" with - being its separator. So all you need to do is to mimic this, this or this to iterate over your nested slash-dash list.

Since your request is relatively simple (only letters and numbers involved), a short TeX code is enough to illustrate how to deal with your comma list nested slash-dash list:

  • First of all \CE takes an argument, the complete list, and passes it to CEii.
  • \CEii takes two arguments separating by /. So the first argument is the substring before the first /. The substring after becomes the second argument. For example Co-Fe-B/MgO/Co-Fe-B is divided into Co-Fe-B and MgO/Co-Fe-B.
  • Now the first argument Co-Fe-B should be the first layer, pass it to \Ce.
  • If the second argument is not empty, then there are more layers coming. Insert a \newslash.
  • Treat the second argument, the other layers MgO/Co-Fe-B, as a new list and start from the beginning. (MgO/Co-Fe-B becomes MgO and Co-Fe-B. Both of them are passed to \Ce in sequence. Another \newslash is inserted between them.)
  • \Ce and Ceii do the same job as CE and CEii. The difference is that it divides the string according to - and inserts \newdash. (Co-Fe-B becomes Co, Fe and B.) And pass these elements to \ce in sequence.
  • (MgO is not an element ... my bad)
  • It is your job to redefine \newskash and \newdash.

\documentclass{article}
\usepackage{mhchem}
\begin{document}

\def\newslash{///}
\def\newdash{---}
\newif\ifmoreelements
\newif\ifmorelayers

\def\Ce#1{%
    \def\templayer{#1}%
    \loop%
        \expandafter\Ceii\templayer-=%
        \expandafter\ce\expandafter{\tempfirstelement}%
    \ifmoreelements%
        \newdash%
        \expandafter\Cei\tempotherelements=%
    \repeat}
\def\Cei#1-={%
    \def\templayer{#1}}
\def\Ceii#1-#2={%
    \def\tempfirstelement{#1}\def\tempotherelements{#2}%
    \ifx\tempotherelements\empty\moreelementsfalse\else\moreelementstrue\fi}
\def\CE#1{%
    \def\tempstack{#1}%
    \loop%
        \expandafter\CEii\tempstack/+%
        {\expandafter\Ce\expandafter{\tempfirstlayer}}%
    \ifmorelayers%
        \newslash%
        \expandafter\CEi\tempotherlayers+%
    \repeat}
\def\CEi#1/+{%
    \def\tempstack{#1}}
\def\CEii#1/#2+{%
    \def\tempfirstlayer{#1}\def\tempotherlayers{#2}%
    \ifx\tempotherlayers\empty\morelayersfalse\else\morelayerstrue\fi}

\CE{Ta/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au}

\end{document}

About Good way

Sometimes I hear people saying that we should never use \def. And the reason is clear: using TeX syntax is in some sense dangerous. For example if one says \CE{-==-+//+-==-}, it will not work as expected. Besides, there are some appearance issues. For example \CE{ Ta // Cu } will call \ce{ Ta } and \ce{ Cu } with spaces while \CE should ignore all spaces around commas.

Nevertheless, it is all up to you. If you KNOW your code will never be like \CE{-==-+//+-==-} and you do like this simple way, then use it. But If you are seeking a way that is powerful and safe, say \DeclareCommaListParser\CE[/][-]{blahblahblah}, then give xparse a chance.

For me, xparse is complicated so far. However if someday LaTeX3 released and those commands are well-documented, I may not answer questions with def anymore.

  • What do you mean by 'because this code works does not mean that it is a good way to do so'? (a) You know, that this code misuses LaTeX in some way. (b) It might or might not be a good way to do it. – Andy Sep 23 '14 at 11:36
  • @Andy I add some words to my answer. – Symbol 1 Sep 23 '14 at 13:47
4

For those using chemformula instead of mhchem there is a quick solution. I suffices to replace / be \slash to allow line breaks after the slash. Since chemformula already has a mechanism for replacing input symbols with output symbols in compounds we only need to access it:

\ExplSyntaxOn
\cs_new_protected:Npn \chemformula_new_compound_property:nn #1#2
  { \prop_put_if_new:Nnn \l__chemformula_cmpd_prop {#1} {#2} }

\NewDocumentCommand \NewChemCompoundProperty { mm }
  { \chemformula_new_compound_property:nn {#1} {#2} }
\ExplSyntaxOff

Now all that's left is saying \NewChemCompoundProperty{/}{\slash}. This makes use of an internal variable so it is not entirely safe but I'm inclined to add something similar to the package.

As for the - being transformed into single bonds – the same is true for chemformula but using chemformula's "..." syntax can help here. Or – using the new command one could say \NewChemCompoundProperty{:}{-} (or something):

\documentclass{article}

\usepackage{chemformula,mhchem}

\ExplSyntaxOn
% I might add this to chemformula:
\cs_new_protected:Npn \chemformula_new_compound_property:nn #1#2
  { \prop_put_if_new:Nnn \l__chemformula_cmpd_prop {#1} {#2} }

\NewDocumentCommand \NewChemCompoundProperty { mm }
  { \chemformula_new_compound_property:nn {#1} {#2} }
\ExplSyntaxOff

\NewChemCompoundProperty{/}{\slash}

\usepackage{showframe}

\begin{document}

Bla.  The layer stack consists of \ch{Ta/Cu/Ta/Cu/Co "-" Fe "-" B/MgO/Co "-"
  Fe "-" B/Ta/Ru/Au} and all layers are sputtered in a bla bla bla

% or even:
\NewChemCompoundProperty{:}{-}

Bla.  The layer stack consists of
\ch{Ta/Cu/Ta/Cu/Co:Fe:B/MgO/Co:Fe:B/Ta/Ru/Au} and all layers are sputtered in
a bla bla bla

\end{document}

enter image description here


Update Version 4.10 (2015/03/16) supports this directly:

\documentclass{article}
\usepackage{chemformula}[2015/03/16]

\NewChemCompoundProperty{/}{\slash}

\usepackage{showframe}

\begin{document}

Bla.  The layer stack consists of \ch{Ta/Cu/Ta/Cu/Co "-" Fe "-" B/MgO/Co "-"
  Fe "-" B/Ta/Ru/Au} and all layers are sputtered in a bla bla bla

% or even:
\NewChemCompoundProperty{:}{-}

Bla.  The layer stack consists of
\ch{Ta/Cu/Ta/Cu/Co:Fe:B/MgO/Co:Fe:B/Ta/Ru/Au} and all layers are sputtered in
a bla bla bla

\end{document}
2

This could work with the new RegExp engine. Out of curiosity, I tried it and found a solution. It's a weird mix of old and new syntax.

\documentclass{article}
\usepackage[version=3]{mhchem}
\usepackage{l3regex}
\begin{document}
\newcommand*\stackslash{\text{/}\allowbreak}
\newcommand*\stackdash{\text{-}\allowbreak}
\ExplSyntaxOn
\newcommand\stack[1] {
  \tl_new:N \l_my_tl
  \tl_set:Nx \l_my_tl { \exp_not:N \ce { #1 } }
  \regex_replace_all:nnN { \/ } { \cE] \c{stackslash} \c{ce}\cB[ } \l_my_tl
  \regex_replace_all:nnN { \- } { \cE] \c{stackdash} \c{ce}\cB[ } \l_my_tl
  \tl_use:N \l_my_tl
}
\ExplSyntaxOff

The layer stack consist of \stack{Ta/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au} and all layers are sputtered in a bla bla bla
\end{document}

Basically, it takes A/B/C-D/E and transforms it into \ce{A}\stackslash\ce{B}\stackslash\ce{C}\stackdash\ce{D}\stackslash\ce{E}.

  • I incorporated this idea of mine into mhchem 3.21. A configurable \cesplit command is provided. Search the manual for the "Layer Stack" example. – mhchem Mar 13 '15 at 20:05
2
+50

With mhchem 3.21, you can use the \cesplit command.

\documentclass{article}
\usepackage[version=3]{mhchem}
\begin{document}
\newcommand*\stackslash{\text{/}\allowbreak}
\newcommand*\stackhyphen{\text{-}\allowbreak}
\newcommand\stack[1]{\cesplit{{\/}{\c{stackslash}}{-}{\c{stackhyphen}}}{#1}}
The layer stack consists of \stack{Ta/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au} and all layers are sputtered in \ldots
\end{document}

enter image description here

1

This is a small Lua snippet demonstrating different approach which passes plain text (ending by space) to Lua, uses regular expressions and passes output back to the TeX engine. It extends a series of text characters except slashes and minuses to the \ce command, changes divis to endash and adds \allowbreak command after each slash.

Let the input is: Cu/Ta/H2O/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au.

The modified text looks like this: \ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{H2O}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{MgO}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Ru}/\allowbreak{}\ce{Au}.

We execute lualatex mal-chem.tex.

\documentclass{article}
\pagestyle{empty}
\usepackage{lipsum}
\usepackage{luacode}
\usepackage[version=3]{mhchem}
\begin{document}
\begin{luacode*}
function malstr(text)
text=string.gsub(text, "[^/-]+", "\\ce{%1}")
text=string.gsub(text, "%-", "--\\allowbreak{}") 
-- -- or --\\allowbreak{}
text=string.gsub(text, "/", "/\\allowbreak{}")
tex.print(text); print(text)
end -- of function malstr
\end{luacode*}
\def\nobonds#1 {\directlua{malstr([[#1]])} }
\lipsum[1]\par
The layer stack consist of \nobonds Cu/Ta/H2O/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au and all layers are sputtered in...
% result is: \ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{H2O}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{MgO}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Ru}/\allowbreak{}\ce{Au}
\end{document}

resulting figure

protected by Community Mar 16 '15 at 7:17

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.