Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Derived units calculation issue #1226

Closed
iomaganaris opened this issue Apr 29, 2021 · 2 comments
Closed

Derived units calculation issue #1226

iomaganaris opened this issue Apr 29, 2021 · 2 comments
Labels
bug units Issues related to the UNITS definition in NEURON

Comments

@iomaganaris
Copy link
Member

iomaganaris commented Apr 29, 2021

Context

NEURON mod translation error in the calculated value for derived units

Overview of the issue

When calculating values of derived units from other units when needed to do a calculation like multiplication or division there is an error in the computed values by mod2c and NEURON.
For example for:

UNITS {
	R = 8.313424 (joule/degC)
	J = (R-mole) (1)
	test = (mole) (1)
}

We have with NEURON:

 static double R = 8.313424;
#define J _nrnunit_J[_nrnunit_use_legacy_]
static double _nrnunit_J[2] = {0x1.0912acba81b67p+82, 5.00711e+24}; /* 5.00708642302769403e+24 */
#define test _nrnunit_test[_nrnunit_use_legacy_]
static double _nrnunit_test[2] = {0x1.fe185ca57c517p+78, 6.02217e+23}; /* 6.02214075999999987e+23 */

With mod2c:

double R = 8.313424;
#pragma acc declare copyin(R)
double J = /* 0x1.0912acba81b67p+82; */ 5.00708642302769403e+24;
 #pragma acc declare copyin(J)
double test = /* 0x1.fe185ca57c517p+78; */ 6.02214075999999987e+23;
 #pragma acc declare copyin(test)

For the above modern units were selected.
Note that hex and decimal numbers match.

Expected result/behavior

From the above we see that mole = 6.02214075999999987e+23, R = 8.313424 and if we calculate by hand J = R*mole we have:

>>> 6.02214075999999987e+23 * 8.313424
5.006460952556223e+24

NEURON setup

  • Version: master branch
  • Installation method: cmake build
  • OS + Version: Ubuntu 20.04
  • Compiler + Version: gcc-10

Minimal working example - MWE

Translate any mod file with:

UNITS {
	R = 8.313424 (joule/degC)
	J = (R-mole) (1)
	test = (mole) (1)
}

Same as: BlueBrain/mod2c#62

@nrnhines
Copy link
Member

nrnhines commented May 1, 2021

The translation values are correct but unexpected to me also. I had to experiment a bit to figure out the semantics. The syntax of the above UNITS block is used to define constants (R, J, and test) that have units, and the right side of the = uses the units database to determine the values of those constants. So R on the left hand side is the name of a constant and R in parentheses
on the right hand side is the name of the gas constant in the units database. Hence in the calculation of J, R is coming from the units database not the previous line constant R.

To add a new unit to the database, one must use the syntax

UNITS {
  (R) = (8 joule/degC)
  (mole) = (6+23)  
  J = (R-mole) (1)
}

but you will get a message on translation like

Redefinition of units (R) to:	8 m2-kg/sec2-K
 is ignored.
They remain:	8.31446 m2-kg/sec2-K
Units redefinition at line 6 in file unitstest3.mod
  (R) = (8 joule/degC)

and if you fix that, then a similar error for mole.
So you would need to introduce new names into the units database with something like

UNITS {
  (myR) = (8 joule/degC)
  (mymole) = (6+23)  
  R = (myR) (1)
  J = (myR-mymole) (1)
}

And then in the translated c file you would see:

static double _nrnunit_R[2] = {0x1p+3, 8}; /* 8 */

#define J _nrnunit_J[_nrnunit_use_legacy_]
static double _nrnunit_J[2] = {0x1.fc3842bd1f072p+81, 4.8e+24}; /* 4.80000000000000013e+24 */

I have a very old units.html file that discusses all this. It needs to be incorporated into the docs. Here are the relevant text fragments.

<h1>Definition of new units</h1>
New units can be defined in terms of default units and previously defined
units by placing definitions in the UNITS block. eg.
<blockquote><pre>
UNITS {
   (uF)    =  (microfarad)
   (Mohms) =  (megohms)
   (V)     =  (volt)
   (molar) =  (/liter)
   (mM)    =  (millimolar)
}
</pre></blockquote>
...
and it is more convenient to define <em>constant</em>
constants in the UNITS block rather
than in the CONSTANTS block --- there is less chance of a typo, and they
do not appear in SCoP where they can be inadvertently changed.
For example:
<blockquote><pre>
UNITS {
   F      = (faraday) (coulomb)
   PI     = (pi) (1)
   e      = (e) (coulomb)
   R      = (k-mole) (joule/degC)
   C      = (c) (cm/sec)
}
</pre></blockquote>
Here,  <code>C</code> is the speed of light in cm/sec and <code>R</code> is the
Gas constant.
<p>
Constant factors are defined in the UNITS block in the following manner.
<blockquote><pre>
UNITS {
   F   = 96520    (coul)
   PI  = 3.14159  ()  
   foot2inch = 12 (inch/foot)
}

@iomaganaris
Copy link
Member Author

The discrepancy in NMODL got fixed in NMODL with BlueBrain/nmodl#1030 so this can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug units Issues related to the UNITS definition in NEURON
Projects
None yet
Development

No branches or pull requests

2 participants