How to extend the elements package to print melting and boiling points?
There you go:
The unit
key (default is kelvin
) sets the input unit in \DeclareAtomMeltingPoint
and output unit for \meltingpoint
. Internally the temperature is stored in Kelvin. The number is printed with no further formatting.
Both the declaration with \DeclareAtomMeltingPoint
and the usage with \meltingpoint
use the atomic number. The element symbol and name is not so easy to retrieve, so the code gets more complicated.
\documentclass{article}
\usepackage{elements}
\usepackage{xparse}
\ExplSyntaxOn
\keys_define:nn { grs / elements }
{
, unit .choice:
, unit / kelvin .code:n = { \cs_set_eq:NN \__grs_select_unit:nnn \use_i:nnn }
, unit / celsius .code:n = { \cs_set_eq:NN \__grs_select_unit:nnn \use_ii:nnn }
, unit / fahrenheit .code:n = { \cs_set_eq:NN \__grs_select_unit:nnn \use_iii:nnn }
, unit .initial:n = kelvin
, unit .value_required:n = true
}
\NewDocumentCommand \DeclareAtomMeltingPoint { o m m }
{
\group_begin:
\IfValueT {#1}
{ \keys_set:nn { grs / elements } {#1} }
\cs_gset:cpx { @elements@atom@meltpoint@ \int_to_roman:n {#2} }
{
\__grs_select_unit:nnn
{ \fp_eval:n {#3} } % kelvin
{ \fp_eval:n {#3 + 273.15} } % celsius
{ \fp_eval:n {(#3 + 459.67)*5/9} } % fahrenheit
}
\group_end:
}
\NewDocumentCommand \meltingpoint { o m }
{
\group_begin:
\IfValueT {#1}
{ \keys_set:nn { grs / elements } {#1} }
\exp_args:Nv \__grs_meltingpoint:n
{ @elements@atom@meltpoint@ \int_to_roman:n {#2} }
\group_end:
}
\cs_new:Npn \__grs_meltingpoint:n #1
{
\__grs_select_unit:nnn
{ #1 } % kelvin
{ \fp_eval:n {#1 - 273.15} } % celsius
{ \fp_eval:n {#1 * 9/5 - 459.67} } % fahrenheit
}
\ExplSyntaxOff
\begin{document}
\DeclareAtomMeltingPoint[unit=celsius]{79}{1064}
\meltingpoint[unit=kelvin]{79}
\meltingpoint[unit=celsius]{79}
\meltingpoint[unit=fahrenheit]{79}
\end{document}
I'd not use unit=
, because this hinders expandability.
I take the approach of using a property list.
\documentclass{article}
\usepackage{xparse,siunitx}
\DeclareSIUnit{\fahrenheit}{\degree F}
\ExplSyntaxOn
\NewDocumentCommand{\DeclareAtomMeltingPoint}{O{kelvin}mm}
{
\group_begin:
\keys_set:nn { grs/meltingpoint } { #1 }
\prop_gput:Nnx \g_grs_meltingpoint_prop { #2 }
{
\__grs_meltingpoint_store:n { #3 }
}
\group_end:
}
\prop_new:N \g_grs_meltingpoint_prop
\keys_define:nn { grs/meltingpoint }
{
kelvin .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_kelvin:n,
K .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_kelvin:n,
celsius .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_celsius:n,
C .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_celsius:n,
fahrenheit .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_fahrenheit:n,
F .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_i_fahrenheit:n,
}
\cs_new:Nn \__grs_meltingpoint_in_kelvin:n
{
\fp_eval:n { #1 }
}
\cs_new:Nn \__grs_meltingpoint_in_celsius:n
{
\fp_eval:n { #1 + 273.15 }
}
\cs_new:Nn \__grs_meltingpoint_in_fahrenheit:n
{
\fp_eval:n { (#1 + 459.67)*5/9 }
}
\NewExpandableDocumentCommand{\meltingpoint}{sO{kelvin}m}
{
\IfBooleanTF{#1}
{ % we want the unit
\str_case:nn { #2 }
{
{kelvin}{\SI{\__grs_meltingpoint_out_kelvin:n{#3}}{\kelvin}}
{K}{\SI{\__grs_meltingpoint_out_kelvin:n{#3}}{\kelvin}}
{celsius}{\SI{\__grs_meltingpoint_out_celsius:n{#3}}{\celsius}}
{C}{\SI{\__grs_meltingpoint_out_celsius:n{#3}}{\celsius}}
{fahrenheit}{\SI{\__grs_meltingpoint_out_fahrenheit:n{#3}}{\fahrenheit}}
{F}{\SI{\__grs_meltingpoint_out_fahrenheit:n{#3}}{\fahrenheit}}
}
}
{ % no unit
\str_case:nn { #2 }
{
{kelvin}{\__grs_meltingpoint_out_kelvin:n{#3}}
{K}{\__grs_meltingpoint_out_kelvin:n{#3}}
{celsius}{\__grs_meltingpoint_out_celsius:n{#3}}
{C}{\__grs_meltingpoint_out_celsius:n{#3}}
{fahrenheit}{\__grs_meltingpoint_out_fahrenheit:n{#3}}
{F}{\__grs_meltingpoint_out_fahrenheit:n{#3}}
}
}
}
\cs_new:Nn \__grs_meltingpoint_out_kelvin:n
{
\prop_item:Nn \g_grs_meltingpoint_prop { #1 }
}
\cs_new:Nn \__grs_meltingpoint_out_celsius:n
{
\fp_eval:n { \prop_item:Nn \g_grs_meltingpoint_prop { #1 } - 273.15 }
}
\cs_new:Nn \__grs_meltingpoint_out_fahrenheit:n
{
\fp_eval:n { \prop_item:Nn \g_grs_meltingpoint_prop { #1 } * 9/5 - 459.67 }
}
\ExplSyntaxOff
\DeclareAtomMeltingPoint[celsius]{79}{1064}
\begin{document}
\meltingpoint*[kelvin]{79}
\meltingpoint[kelvin]{79}
\meltingpoint*[K]{79}
\meltingpoint[K]{79}
\meltingpoint*[celsius]{79}
\meltingpoint[celsius]{79}
\meltingpoint*[C]{79}
\meltingpoint[C]{79}
\meltingpoint*[fahrenheit]{79}
\meltingpoint[fahrenheit]{79}
\meltingpoint*[F]{79}
\meltingpoint[F]{79}
\end{document}
You can use either the long name or the initial, for ease of input. The *
-version uses \SI
to typeset the value with the required unit.
The declaration can use any unit, the value is stored in kelvin.
A slightly different version with support also for boiling points and avoiding code duplication.
\documentclass{article}
\usepackage{xparse,siunitx}
\DeclareSIUnit{\fahrenheit}{\degree F}
\ExplSyntaxOn
\NewDocumentCommand{\DeclareAtomMeltingPoint}{O{kelvin}mm}
{
\prop_gput:Nnx \g_grs_meltingpoint_prop { #2 }
{
\use:c { __grs_temperature_in_#1:n } { #3 }
}
}
\NewDocumentCommand{\DeclareAtomBoilingPoint}{O{kelvin}mm}
{
\prop_gput:Nnx \g_grs_boilingpoint_prop { #2 }
{
\use:c { __grs_temperature_in_#1:n } { #3 }
}
}
\NewExpandableDocumentCommand{\meltingpoint}{sO{kelvin}m}
{
\IfBooleanTF{#1}
{ % we want the unit
\grs_point_si:Nnn \g_grs_meltingpoint_prop { #2 } { #3 }
}
{
\grs_point:Nnn \g_grs_meltingpoint_prop { #2 } { #3 }
}
}
\NewExpandableDocumentCommand{\boilingpoint}{sO{kelvin}m}
{
\IfBooleanTF{#1}
{ % we want the unit
\grs_point_si:Nnn \g_grs_boilingpoint_prop { #2 } { #3 }
}
{
\grs_point:Nnn \g_grs_boilingpoint_prop { #2 } { #3 }
}
}
\prop_new:N \g_grs_meltingpoint_prop
\prop_new:N \g_grs_boilingpoint_prop
\cs_new:Nn \__grs_temperature_in_kelvin:n
{
\fp_eval:n { #1 }
}
\cs_set_eq:NN \__grs_temperature_in_K:n \__grs_temperature_in_kelvin:n
\cs_new:Nn \__grs_temperature_in_celsius:n
{
\fp_eval:n { #1 + 273.15 }
}
\cs_set_eq:NN \__grs_temperature_in_C:n \__grs_temperature_in_celsius:n
\cs_new:Nn \__grs_temperature_in_fahrenheit:n
{
\fp_eval:n { (#1 + 459.67)*5/9 }
}
\cs_set_eq:NN \__grs_temperature_in_F:n \__grs_temperature_in_fahrenheit:n
\cs_new:Nn \__grs_temperature_out_kelvin:Nn
{
\prop_item:Nn #1 { #2 }
}
\cs_new:Nn \__grs_temperature_out_celsius:Nn
{
\fp_eval:n { (\prop_item:Nn #1 { #2 }) - 273.15 }
}
\cs_new:Nn \__grs_temperature_out_fahrenheit:Nn
{
\fp_eval:n { (\prop_item:Nn #1 { #2 }) * 9/5 - 459.67 }
}
\cs_new:Nn \grs_point_si:Nnn
{
\str_case:nn { #2 }
{
{kelvin}{\__grs_point_si:NNnn #1 \__grs_temperature_out_kelvin:Nn {#3} {\kelvin}}
{K}{\__grs_point_si:NNnn #1 \__grs_temperature_out_kelvin:Nn {#3} {\kelvin}}
{celsius}{\__grs_point_si:NNnn #1 \__grs_temperature_out_celsius:Nn {#3} {\celsius}}
{C}{\__grs_point_si:NNnn #1 \__grs_temperature_out_celsius:Nn {#3} {\celsius}}
{fahrenheit}{\__grs_point_si:NNnn #1 \__grs_temperature_out_fahrenheit:Nn {#3} {\fahrenheit}}
{F}{\__grs_point_si:NNnn #1 \__grs_temperature_out_fahrenheit:Nn {#3} {\fahrenheit}}
}
}
\cs_new:Nn \grs_point:Nnn
{
\str_case:nn { #2 }
{
{kelvin}{\__grs_point:NNn #1 \__grs_temperature_out_kelvin:Nn {#3}}
{K}{\__grs_point:NNn #1 \__grs_temperature_out_kelvin:Nn {#3}}
{celsius}{\__grs_point:NNn #1 \__grs_temperature_out_celsius:Nn {#3}}
{C}{\__grs_point:NNn #1 \__grs_temperature_out_celsius:Nn {#3}}
{fahrenheit}{\__grs_point:NNn #1 \__grs_temperature_out_fahrenheit:Nn {#3} }
{F}{\__grs_point:NNn #1 \__grs_temperature_out_fahrenheit:Nn {#3} }
}
}
\cs_new_protected:Nn \__grs_point_si:NNnn
{
\SI{#2 #1 {#3}}{#4}
}
\cs_new:Nn \__grs_point:NNn
{
#2 #1 {#3}
}
\ExplSyntaxOff
\DeclareAtomMeltingPoint[celsius]{79}{1064}
\DeclareAtomBoilingPoint[celsius]{1}{-252.9}
\begin{document}
\meltingpoint*[kelvin]{79}
\meltingpoint[kelvin]{79}
\meltingpoint*[K]{79}
\meltingpoint[K]{79}
\meltingpoint*[celsius]{79}
\meltingpoint[celsius]{79}
\meltingpoint*[C]{79}
\meltingpoint[C]{79}
\meltingpoint*[fahrenheit]{79}
\meltingpoint[fahrenheit]{79}
\meltingpoint*[F]{79}
\meltingpoint[F]{79}
\boilingpoint*[kelvin]{1}
\boilingpoint[kelvin]{1}
\boilingpoint*[K]{1}
\boilingpoint[K]{1}
\boilingpoint*[celsius]{1}
\boilingpoint[celsius]{1}
\boilingpoint*[C]{1}
\boilingpoint[C]{1}
\boilingpoint*[fahrenheit]{1}
\boilingpoint[fahrenheit]{1}
\boilingpoint*[F]{1}
\boilingpoint[F]{1}
\end{document}