Scientific Units
It is quite common in science subjects to need to accept an answer which has units, for example using .
Currently STACK only support SI units. See International Bureau of Weights and Measures (2006), (The International System of Units (SI)) PDF (8th ed.), ISBN 92-822-2213-6.
Maxima packages for the support of scientific units
In Maxima there are a number of separate packages which enable a user to manipulate physical units.
load(unit);
the code is in...\share\contrib\unit\unit.mac
load(units);
the code is in...\share\physics\units.mac
load(ezunits);
the code is in...\share\ezunits\ezunits.mac
WE DO NOT USE THESE PACKAGES as they are too slow to load and have a variety of side effects. Instead we have a lightweight package of our own.
By default in Maxima, letters such as k
are unbound variables. If you would like to give these prefix values so that km
literally means 10^3*m
then you will need to add the following to the question variables field.
stack_unit_si_declare(true);
The units input and units answer test automatically execute this command. More details are given below.
Internally numbers can be separated from units using the following inert Maxima function.
stackunits(num, units)
where num
is the part interpreted to be the numerical portion, and units
is the portion considered to be the units. For example, in the expression 10*m/s
the internal value from this input will be stackunits(10,m/s)
. Essentially the function stackunits
is inert, but does subtly modify the display. However, having STACK split the student's answer this way is more reliable than teachers trying to find the "numerical part" themselves on a question by question basis. It essentially creates a single object representing a dimensional numerical quantity. If you are using the units answer tests then you need not worry about these internals.
Examples
An example question is given in the stacklibrary Topics\Topics_units_basic.xml
Example 1
Let us assume that the correct answer is 12.1*m/s^2
.
- Students type this value into STACK exactly as it is above. Note the multiplication sign between the number and units. There are options to condone a missing star, or to accept a space.
- In entry, the numerical part is bound to the units part with multiplication. Using multiplication in this way is ambiguous. To create, and to disambiguate, a dimensional numerical quantity from a number multiplied by units (a subtle distinction at best) STACK has a mostly inert function
stackunits(12.1,m/s^2)
. Students do not need to use this, but teachers can use it in question variables etc. - STACK converts the student's answer to SI base units only.
This function also handles the number coefficients automatically (e.g.
1*km = 1000*m
etc.). - STACK has answer tests which compare dimensional numbers. These tests use (share code with) one of the existing numerical answer tests, such as
NumSigFigs
.
Input type
Stack provides an input type to enable teachers to support students in entering answers with scientific units.
The goal of this input is to validate against the pattern number * units
.
- The input type will check both the teacher's answer and the student's answer for units. The input will require the student's answer to have units if and only if the teacher's answer also has units. This normally forces the student to use units. Also, students sometimes add units to dimensionless quantities (such as pH) and this input type will also enable a teacher to reject such input as invalid when the teacher does not use units.
- In validating against the pattern
number * units
we do not accept complex expressions which might simplify to this with some additional calculations. For example, an answer such as9.4*m-53*cm
is not considered valid by this input. - This input type always accepts floating-point numbers, regardless of the option set on the edit form. The input type should display the same number of significant figures as typed in by the student. Note that all other input types truncate the display of unnecessary trailing zeros in floating point numbers, loosing information about significant figures. If you want to specifically test for significant figures, use this input type, with the teacher's answer having no units.
- The student must type a number of some kind. Entering units on their own will be invalid. If you want to ask a student for units, then use the algebraic input type. Units on their own are a not valid expression for this input.
- If the teacher shows the validation, "with variable list" this will be displayed as "the units found in your answer are"...
- The student is permitted to use variable names in this input type.
- The "insert stars" option is unchanged. You may or may not want your students to type a
*
or space between the numbers and units for implied multiplication. - You may want the single letter variable names options here. Note that since
km
literally meansk*m=1000*m
this is not a problem with most units. - The input type checks for units in a case sensitive way. If there is more than one option then STACK suggests a list. E.g. if the student types
mhz
then STACK suggestsMHz
ormHz
. - You can require numerical accuracy at validation by using the
mindp
,maxdp
,minsf
andmaxsf
extra options, as documented in the numerical input.
There are surprisingly few ambiguities in the units set up, but there will be some that the developers have missed (correctly dealing with ambiguous input is by definition an impossible problem!). Please contact us with suggestions for improvements.
Note, the input does not currently support a situation where you want to accept as valid a purely numerical quantity and then use the PRT to deduct marks for failing to use units, rather than rejecting it as invalid.
Extra Options
The extra options to the input should be a comma separated list of tags. This input type makes use of the additional options in two ways:
- Units can be displayed using inline fractions or negative powers . Add
negpow
to the Extra Options field to use negative powers.
Answer tests
STACK provides a number of answer tests for dealing with units. These are designed to accept an answer which is a dimensional numerical quantity, that is a floating-point number with units such as 12.3*m/s
. This will not work with sets, lists, matrices, equations, etc.
The answer tests require the teacher's answer (second argument to the function) to have units. If the teacher does not specify units then the test will fail. This decision is to help question authors write robust questions e.g. just specifying a number would be problematic. The input will accept an answer as valid if and only if the teacher's answer has units, so you should know in advance if you have units. If you want to compare numbers (i.e. no units), just use the numerical test.
The units answer tests will happily accept a stackunits
expression. Otherwise, the answer test splits up both arguments into this form first.
There are three decisions to be made:
- Does the written precision matter? I.e. should the student use certain significant figures? If so, should we take a strict interpretation of significant figures ( has 1 sig fig, has 3) or not ( has somewhere between 1 and 3 sig figs)? See the
NumSigFigs
andSigFigsStrict
answer tests. - How does numerical precision matter? A number might be written using significant figures, but is it the right number? See the
NumSigFigs
,NumRelative
andNumAbsolute
answer tests. - Do we convert to compatible units, or require strict units which match those given by the teacher exactly?
Essentially, the teacher has to make three decisions. These could always be done in a potential response tree with three nodes, but this is a common task. For legacy reasons, some of the answer tests (e.g. NumSigFigs
, UnitsSigFigs
) combine answering two or more of these questions in one answer test.
For scientific units (Q3.) there are two families of answer tests.
Units[...]
gives feedback if the student has the wrong units, but number is equivalent on conversion,UnitsStrict[...]
expects the student's answer to use exactly the units which appear in the teacher's answer. There is no conversion here. However, answer notes will record whether the conversion would have worked.
The two issues related to the numerical part are tested with one of the numerical answer tests which are documented elsewhere. Units answer tests share code with these functions. Use the appropriate options for the chosen test.
Notes
- All variables are considered to be units.
- The numerical part is compared using the one of the three numerical answer tests. Each requires various options, e.g. the number of significant figures, or the numerical accuracy. These answer tests use identical options to the numerical tests.
- The units system accepts both
l
andL
for litres, and the display respects the way they are typed in. - Only abbreviations are accepted, not full names. I.e. students may not use
meter
, instead they must usem
. - Currently there is no localisation (i.e. language support) for unit names/spellings.
- The letter
u
is the prefix for micro, and is displayed as when the student validates. - The string
xi
is the Greek letter . If you assume single variable letter names this might clash withx*i
which is a relatively common pattern.
Conversion to base units and numerical accuracy
This only applies to the "non-strict" versions of the tests. If the units in the student's answer do not match those of the teacher, then both the student's and teacher's answer is converted to base scientific units and the numerical test applied again. Note, the student's answer is not converted to the units used by the teacher.
For example, in order to make a numerical comparison between 1.1*Mg/10^6
and 1.2*kN*ns/(mm*Hz)
both expressions are converted to base units of kg
. The numerical test is then applied.
For the NumRelative
test the option gives the required percentage tolerance within which a student's answer should be. Literally we test the following |sa-ta| < |ta*tol|
. Here sa
and ta
are the numerical value of the student's and teacher's answer respectively. The same tol
is used both when the units match and once they have been converted to base units.
Similarly, for NumAbsolute
the option is an absolute difference, (expressed in units). Literally we test
|sa-ta| < |tol|
. Here sa
and ta
are the numerical value of the student's and teacher's answer respectively once they have been converted to base units. If tol
has no units, then STACK will use the units supplied by the teacher.
If the teacher uses units in the option then the option units must be identical to the units in the teacher's answer.
Dealing with units in Maxima functions, e.g. question variables and PRTs
STACK uses an inert function to represent dimensional numerical quantities.
stackunits(num, units)
In particular, if we just represented scientific units as a product there would be no way to distinguish between stackunits(0, m)
and stackunits(0, s)
. As a product both would evaluate to 0
, which would appear dimensionless. A teacher is still likely to want to make comments on units when the numerical part is zero.
The function stack_unit_si_declare(true)
declares variables as units. (Note the argument to this function is not used.) For example, this changes the TeX output of m
to Roman and not the normal . (That units are displayed in Roman is lost to most students!). Note that the symbols are only declared to be units by using stack_unit_si_declare(true)
first somewhere else in the question, or feedback variables.
unitsp(ex)
is a predicate which decides if STACK considers the expression to represent a dimensional numerical quantitystackunits
.listofnonunits(ex)
lists all variables in the expressionex
considered not to be units however they appear. Use of this function auto-loadsstack_unit_si_declare(true)
.listofunits(ex)
lists all variables in the expressionex
considered to be units however they appear. Use of this function auto-loadsstack_unit_si_declare(true)
.- If you do not declare
stack_unit_si_declare(true)
in the question variables you may need to do so in the feedback text itself. - If you are manipulating two expressions and you want to ensure they both use the same units use
stack_unit_si_to_si_base(ex)
on each. This ensures only the base units of SI are used. E.g.stack_unit_si_to_si_base(stackunits(12.1,km))
givesstackunits(12100.0,m)
.
This function declares all units in one go, and there is no way to declare only a subset. Indeed, using only a subset would disrupt the conversion logic. Defining all the units restricts the number of variable names available in a particular question, e.g. is assumed to represent Farad, and all units are typeset in Roman type, e.g. rather than the normal . If you need to fine-tune the display how do to so if explained in the atoms and subscripts section of the more general Maxima documentation.
The function stackunits_make(ex)
takes the expression ex
and, if this is a product of numbers and units, it returns an inert function stackunits
with arguments stackunits(numbers, symbols)
. Note, symbols will include a mix of variables, and symbols which are considered to be units. Use of this function autoloads stack_unit_si_declare(true)
.
The function stackunits_to_product(ex)
turns a stackunits
object into a product of number and units.
It might be helpful in the feedback variables field to separate units from numerical parts prior to building your own potential response tree. However, do not do the following.
n:float(100+rand(300)/10);
u:m/s
ta:stackunits_make(n*u)
Instead just call stackunits
directly
n:float(100+rand(300)/10);
u:m/s
ta:stackunits(n,u)
If you regularly find yourself building a particular tree to test for some property please contact the developers who will consider adding this functionality to the core.
The functions
stack_units_units(ex);
stack_units_nums(ex);
try to split the expression into units and numbers, and the return the units and numbers found. If there are no numbers, stack_units_nums(ex)
returns NULLNUM
. If there are no numbers, stack_units_units(ex)
returns NULLUNITS
. These are special tags, but note they are displayed by LaTeX as empty strings. (You could also use first(args(ans1))
or second(args(ans1))
respectively to access the numerical and units parts.)
The reason for having NULLNUM
is so that we can tell the difference between m/s
and 1m/s
. If you want to use the value in an answer test and don't care about the difference (or want NULLNUM=1
) then use ev(stack_units_nums(ex),NULLNUM=1)
.
The function stack_units_split
is deprecated. DO NOT USE.
Fine-tuning the display
By default STACK's TeX function prints out stackunits(10,m/s)
as . That is, without any multiplication sign between the numerical part and the units. In some edge cases you might want to add this multiplication sign in. To do this, use
texput(multsgnstackunits, "\\cdot");
in the question variables. In castext you can use, e.g. {@(texput(multsgnstackunits, "\\cdot "), stackunits(1, s^-1))@}
to create output .
Custom units
The teacher may want to use their own units. For example, the core unit
package in Maxima does not include mm
(millimetre), it is defined there as a word millimetre
. This is one reason for creating our own custom units package.
For advanced users and developers only
Currently there is no way to create custom sets of units. This feature may be added in the future. The following may be helpful for now, but this does not fully work and the mechanism will change in the future when proper support is added for custom units.
Add the following to the question variables and feedback variables.
stack_unit_si_declare(true);
declare(diamonds, units);
texput(diamonds, "\\diamond");
The symbol diamonds
will then be treated as units in code such as unitsp(ex)
and displayed with the TeX symbol.
You will need to put diamonds
in the allow words of the input in the question.
Tips for dealing with units in STACK
CAS variables are tricky.
- When creating worked solutions etc. try
12.3m*s^(-1)
not12.3m/s
. The display is better. The answer test accepts either as equivalent. - Which units are supported? It is probably best to look at the code. This is contained in
qtype_stack\stack\cas\casstring_units_class.php
. Comments and additions are welcome.