unitsofmeasurement / indriya

JSR 385 - Reference Implementation
Other
115 stars 40 forks source link

How SystemUnit is figured out? #361

Closed kelemenb-ewit closed 2 years ago

kelemenb-ewit commented 2 years ago

I want to define units in Concentration. CUBIC_METRE_PER_CUBIC_METRE can be AbstractUnit.ONE.alternate("m³/m³") or AlternateUnit.of(AbstractUnit.ONE, "m³/m³", null)

But how can I define CUBIC_CENTIMETRE_PER_CUBIC_METRE (cm³/m³) to have system unit m³/m³? It is always "one" for me.

(Btw. how should I apply "asType()" for quantityConcentration<Volume>?)

Thanks!

andi-huber commented 2 years ago

For consistency there can only be one unit representing ONE. See also https://github.com/unitsofmeasurement/indriya/issues/338#issuecomment-791416311

kelemenb-ewit commented 2 years ago

Let me detail my problem. Let's assume we have introduced volumetric concentration with system unit m³/m³. Like this:

Unit<Concentration<Volume>> CUBIC_METRE_PER_CUBIC_METRE =
            addUnit((Unit<Concentration<Volume>>) AlternateUnit.of(
                AbstractUnit.ONE, "m³/m³", null))

If I want to make cm³/m³ you might say I should do

Unit<Concentration<Volume>> CUBIC_CENTIMETRE_PER_CUBIC_METRE_FALSE =
            CENTI(CUBIC_METRE_PER_CUBIC_METRE)

While the CUBIC_CENTIMETRE_PER_CUBIC_METRE_FALSE.getSystemUnit() show the correct "m³/m³", this is not the thing I want, as this is "c(m³/m³)".

Instead, what I do is

        Unit<Volume> cubicCentriMetre = new ProductUnit<>(CENTI(METRE).pow(3));
        Unit<Volume> cubicMetre = new ProductUnit<>(METRE.pow(3));
        Unit<Concentration<Volume>> CUBIC_CENTIMETRE_PER_CUBIC_METRE_RIGHT =
            new ProductUnit<>(cubicCentriMetre.divide(cubicMetre));

But here the CUBIC_CENTIMETRE_PER_CUBIC_METRE_RIGHT.getSystemUnit() returns "one".

How can I achieve to have systemUnit for cm³/m³ of type m³/m³ instead of type one?

Thanks!

andi-huber commented 2 years ago

Both cm³/m³ and m³/m³ are dimensionless Units. These are indistinguishable from 10^-6 x AbstractUnit.ONE or AbstractUnit.ONE respective. Hence, the framework always simplifies dimensionless Units to AbstractUnit.ONE (scaled if required).

andi-huber commented 2 years ago

In other words: AlternateUnit.of(AbstractUnit.ONE, "m³/m³", null)) is not a supported idiom.

kelemenb-ewit commented 2 years ago

Thank you for your fast reply, but I sill don't get it. What about

RADIAN = addUnit(AlternateUnit.of(AbstractUnit.ONE, "rad", "Radian"), Angle.class)

can be found in tech.units.indriya.AbstractSystemOfUnits?

I can say KILO(RADIAN) and the system unit of it is RADIAN, that seams to be a supported and reasonable way to go.

andi-huber commented 2 years ago

Fair point. But RADIAN is a 'pseudo' unit, which is treated as its own thing, which needs explicit conversion to Unit AbstractUnit.ONE if desired.

You can define your own concentration unit m³/m³ by the name of CUBIC_CENTIMETRE_PER_CUBIC_METRE, but this then is also a 'pseudo' unit.

kelemenb-ewit commented 2 years ago

To be a pesudo unit is perfectly okay for me right now. So assuming that, the question still stands:

How can I achieve to have systemUnit for cm³/m³ of type m³/m³ instead of type one?

(The same way as the system unit of centiradian is radian.)

andi-huber commented 2 years ago

Well cm³/m³ would be its own unit as well, with no relationship to m³/m³.

kelemenb-ewit commented 2 years ago

I understand your point, still I don't like this answer. :) Thanks anyway!