Typesetting differential equations
Posted on September 18, 2017
This semester I am teaching a course involving linear differential equations, so I have typeset many differential equations that look like this:
Believe me, writing such equations by hand gets tedious very quickly. So, I
wanted a macro \LDE
(for Linear Differential Equation), so that I
could just type
\LDE{1, -3, 2}{2, 1}
and get the above result. This post describes how to write such a macro using LuaTeX + ConTeXt.
I’ll explain the implementation using a top-down approach. Writing macros in TeX is tough, so let’s delegate all the high lifting to Lua. So, we define a ConTeXt command that simply invokes a Lua function with the appropriate arguments. This can be done using:
\startluacode
-- ... lua function LDE to be added ...
interfaces.definecommand {
name = "LDE",
macro = LDE,
arguments = {
{"content", "list" },
{"content", "list" },
}
}
\stopluacode
The name
argument specifies the name of the TeX command (\LDE
in this case); the macro
argument specifies the name of the Lua function (LDE
in this case) which gets called when the TeX macro is invoked; the arguments
tables specifies the list of arguments of the TeX macros. We specify that the macro has two arguments, both of them are content
arguemnts (that is, the macro is invoked as \LDE{...}{...}
) and each arguement should be passed on to the Lua function as a list
(i.e., a Lua table of strings; other options include hash
(for key-value list), number
, and string
).
Now all we need to do is define the function LDE
, which takes two comma
separated lists as arguments and typesets the resulting differential equation.
The basic logic is straight forward. Suppose we have defined a function
derivative
that typesets a derivative (taking care of adding a +
sign if
the coefficient of an intermediate term is positive; not showing the
coefficient if the coefficient is +1
or -1
; and not showing the term if
the coefficient is 0
). Then, the LDE
function is:
\startluacode
-- Lua function derivative to be added
local LDE = function(LHS, RHS)
for i = 1, #LHS do
context(derivative(LHS[i], "y(t)", #LHS - i, i == 1))
end
context("=")
for i = 1, #RHS do
context(derivative(RHS[i], "u(t)", #RHS - i, i == 1))
end
end
interfaces.definecommand { ... }
\stopluacode
The last term in the call to the derivative
function passes a flag that
indicates whether or not the term is the first term.
I’ll not go into the details of the derivative
function because it is
straight forward. So, here is the complete macro with a usage example:
\startluacode
local find, format = string.find, string.format
local derivative = function(coefficient, var, order, first)
-- If the coefficient is zero or empty, don't typeset anything
if coefficient == nil or coefficient == "" or coefficient == "0" then
return
end
-- If the coefficient is 1 or -1, we do not want to print the 1.
if coefficient == "1" then
coefficient = ""
elseif coefficient == "-1" then
coefficient = "-"
end
-- If this is not the first coefficient by is a positive coefficient,
-- then add a "+" sign
if not first then
if find(coefficient, "-") ~= 1 then
coefficient = "+" .. coefficient
end
end
-- Format the return value depending on the order of the derivative
local str
if order == 0 then
str = format("%s %s", coefficient, var)
elseif order == 1 then
str = format("%s \\dfrac{ d %s } { dt }", coefficient, var)
else
str = format("%s \\dfrac{ d^{%s} %s } { dt^{%s} }", coefficient, order, var, order)
end
return str
end
local LDE = function(LHS, RHS)
LHS = settings_to_array(LHS)
RHS = settings_to_array(RHS)
for i = 1, #LHS do
context(derivative(LHS[i], "y(t)", #LHS - i, i == 1))
end
context("=")
for i = 1, #RHS do
context(derivative(RHS[i], "u(t)", #RHS - i, i == 1))
end
end
interfaces.definecommand {
name = "LDE",
macro = LDE,
arguments = {
{"content", "list" },
{"content", "list" },
}
}
\stopluacode
\starttext
\startformula
\LDE{2,1,-3}{4,0,6}
\stopformula
\startformula
\LDE{a_2, -a_1,a_0}{b_1,b_0}
\stopformula
\stoptext
This entry was posted in Macros and tagged luatex, programming, separating content and presentation.