Closed splatch closed 6 months ago
While I don't know the particular domain, it is possible, the definition of WATTHOUR
above might be incorrect.
See Wikipedia: Kilowatt-hour
Or What is a watt hour (Wh)?
Please have a look at the domain-specific EnergyDemo. There's also a CO2CarDemo.
I am also not sure, why EmissionMass
needs to be defined? Isn't it the same as Mass
?
Also it looks like you made a mistake in above code snippet, because the constructor (why not use getQuantity
here, too?)
ComparableQuantity<EmissionRatio> emissionRatio = new EmissionRatio(800, EmissionRatioUnitSystem.MWH_KG_CO2);
uses MWH_KG_CO2
and ignores the KILO(WH)
.
@splatch I took the freedom to move this to domain-specific demos, because it has nothing to do with Indriya, nor does it seem to be a problem in the RI.
@keilw Thank you for quick answer, I don’t mind move. :) The domain is flexible I guess, since these are derivative (maybe even abstract) units. My starting point was indeed car/fuel/consumption demo you linked.
I began with emission statement published by one of institutes within Poland which says that electricity consumption of 1 MWh
results in emission of 800 kgCO2
. There are some other fractions which are delivered from 1 MWh
, defined in a similar way.
Purpose of EmissionMass
is to keep a relation between a specific gas and mass, based on emission ratio. Ratios are not static (it depends what energy source and its characteristic is), hence another quantity to express relation of MWh
to kgCO2
For Wh
I've used constant from si-units which should keep it close to base units.
the EmissionRatioQuantity
was really my experiment to see if I can intercept math operations and i.e. unify multiplier to common energy unit used by emission ratio. It does not influence results - its just an extension of NumberQuantity
with debug statements and super calls.
Maybe, a better choice for EmissionMass
would be AnnotatedUnit
based on a Mass
? It didn't work.
I reverted to my experiment with custom Quantity
with manual conversion of multiplier to MWh, then I get valid result of 0.8000 kg·CO₂
. Conversion code is rather trivial, real question - is it really necessary?
public class EmissionRatio extends DebugQuantity<EmissionRatio> {
@Override
public ComparableQuantity<?> multiply(Quantity<?> that) {
if (that.getUnit().isCompatible(MWH)) {
Number mwh = that.getUnit().getConverterTo((Unit) MWH).convert(that.getValue());
ComparableQuantity<Energy> quantity = Quantities.getQuantity(mwh, MWH);
return super.multiply(quantity);
}
return super.multiply(that);
}
}
Diving more, below code works, but it does not use metric prefixes:
public class ConversionTests {
public interface Emission extends Quantity<Emission> {} // gas i.e CO2
public interface EmissionMass extends Quantity<EmissionMass> {} // mass of given gass
public interface EmissionRatio extends Quantity<EmissionRatio> {} // mass ratio for given energy
// energy
public static final Unit<Energy> WH = new ProductUnit<>(WATT.multiply(HOUR));
public static final Unit<Energy> KWH = MetricPrefix.KILO(WH);
public static final Unit<Energy> MWH = MetricPrefix.MEGA(WH);
// emission
public static final Unit<Emission> CO2 = new AlternateUnit<>(AbstractUnit.ONE, "CO₂");
public static void main(String[] args) {
Unit<EmissionMass> massUnit = new AlternateUnit<>(KILOGRAM.multiply(CO2), "kg·CO₂").asType(EmissionMass.class);
System.out.println("Emission mass unit " + massUnit);
ComparableQuantity<EmissionMass> massQty = Quantities.getQuantity(1, massUnit);
System.out.println("Emission mass prime " + massQty);
Unit<EmissionRatio> emissionRateUnit = massUnit.divide(WH).asType(EmissionRatio.class);
System.out.println("Emission rate " + emissionRateUnit);
ComparableQuantity<EmissionRatio> emissionRateQty = Quantities.getQuantity(0.0008, emissionRateUnit);
System.out.println("Emission rate prime " + emissionRateQty);
ComparableQuantity<Energy> one_MWh = Quantities.getQuantity(1000000, WH);
System.out.println("Emission from " + one_MWh + ": " + one_MWh.multiply(emissionRateQty));
ComparableQuantity<Energy> one_kWh = Quantities.getQuantity(1000, WH);
System.out.println("Emission from " + one_kWh + ": " + one_kWh.multiply(emissionRateQty));
ComparableQuantity<Energy> oneWH = Quantities.getQuantity(1, WH);
System.out.println("Emission from " + oneWH + ": " + oneWH.multiply(emissionRateQty));
/* output
Emission mass unit kg·CO₂
Emission mass prime 1 kg·CO₂
Emission rate kg·CO₂/(W·h)
Emission rate prime 0.0008 kg·CO₂/(W·h)
Emission from 100000 W·h: 800.0000 kg·CO₂
Emission from 1000 W·h: 0.8000 kg·CO₂
Emission from 1 W·h: 0.0008 kg·CO₂
*/
}
}
Switching last lines to:
ComparableQuantity<Energy> one_MWh = Quantities.getQuantity(1, MWH);
System.out.println("Emission from " + one_MWh + ": " + one_MWh.multiply(emissionRateQty));
ComparableQuantity<Energy> one_kWh = Quantities.getQuantity(1, KWH);
System.out.println("Emission from " + one_kWh + ": " + one_kWh.multiply(emissionRateQty));
ComparableQuantity<Energy> oneWH = Quantities.getQuantity(1, WH);
System.out.println("Emission from " + oneWH + ": " + oneWH.multiply(emissionRateQty));
/* output
Emission mass unit kg·CO₂
Emission mass prime 1 kg·CO₂
Emission rate kg·CO₂/(W·h)
Emission rate prime 0.0008 kg·CO₂/(W·h)
Emission from 1 M(W·h): 0.0008 M(W·h)·kg·CO₂/(W·h)
Emission from 1 k(W·h): 0.0008 k(W·h)·kg·CO₂/(W·h)
Emission from 1 W·h: 0.0008 kg·CO₂
*/
Causes output for 1 MWh
and 1 kWh
to retain the emission mass unit and apply scaling according to provided defined emission ratio. I suppose this shouldn't be a case, since there is common base unit and metric prefix is just a scale.
Earlier you didn't use those prefixes, in the last patch you did, that is correct. creating the quantities
If you want to use the base unit like WH, you'll have to convert to that unit first, see the last line of:
package tech.uom.demo.energy;
import static tech.units.indriya.unit.Units.*;
import javax.measure.MetricPrefix;
import javax.measure.Quantity;
import javax.measure.Unit;
import javax.measure.quantity.Energy;
import tech.units.indriya.AbstractUnit;
import tech.units.indriya.quantity.Quantities;
import tech.units.indriya.unit.AlternateUnit;
import tech.units.indriya.unit.ProductUnit;
public class EmissionDemo {
private static interface Emission extends Quantity<Emission> {} // gas i.e CO2
private static interface EmissionMass extends Quantity<EmissionMass> {} // mass of given gass
private static interface EmissionRatio extends Quantity<EmissionRatio> {} // mass ratio for given energy
// energy
public static final Unit<Energy> WH = new ProductUnit<>(WATT.multiply(HOUR));
public static final Unit<Energy> KWH = MetricPrefix.KILO(WH);
public static final Unit<Energy> MWH = MetricPrefix.MEGA(WH);
// emission
public static final Unit<Emission> CO2 = new AlternateUnit<>(AbstractUnit.ONE, "CO₂");
public static void main(String[] args) {
Unit<EmissionMass> massUnit = new AlternateUnit<>(KILOGRAM.multiply(CO2), "kg·CO₂").asType(EmissionMass.class);
System.out.println("Emission mass unit " + massUnit);
Quantity<EmissionMass> massQty = Quantities.getQuantity(1, massUnit);
System.out.println("Emission mass prime " + massQty);
Unit<EmissionRatio> emissionRateUnit = massUnit.divide(WH).asType(EmissionRatio.class);
System.out.println("Emission rate " + emissionRateUnit);
Quantity<EmissionRatio> emissionRateQty = Quantities.getQuantity(0.0008, emissionRateUnit);
System.out.println("Emission rate prime " + emissionRateQty);
Quantity<Energy> one_MWh = Quantities.getQuantity(1000000, WH);
System.out.println("Emission from " + one_MWh + ": " + one_MWh.multiply(emissionRateQty));
Quantity<Energy> one_kWh = Quantities.getQuantity(1000, WH);
System.out.println("Emission from " + one_kWh + ": " + one_kWh.multiply(emissionRateQty));
Quantity<Energy> oneWH = Quantities.getQuantity(1, WH);
System.out.println("Emission from " + oneWH + ": " + oneWH.multiply(emissionRateQty));
Quantity<Energy> true_one_MWh = Quantities.getQuantity(1, MWH);
System.out.println("Emission from " + true_one_MWh + ": " + true_one_MWh.multiply(emissionRateQty));
System.out.println("Emission from " + true_one_MWh + ": " + true_one_MWh.to(WH).multiply(emissionRateQty));
System.out.println("Equivalent? " + true_one_MWh.isEquivalentTo(one_MWh));
/* output
Emission mass unit kg·CO₂
Emission mass prime 1 kg·CO₂
Emission rate kg·CO₂/(W·h)
Emission rate prime 8.0E-4 kg·CO₂/(W·h)
Emission from 1000000 W·h: 800 kg·CO₂
Emission from 1000 W·h: 0.80000 kg·CO₂
Emission from 1 W·h: 0.00080 kg·CO₂
Emission from 1 M(W·h): 0.00080 M(W·h)·kg·CO₂/(W·h)
MWh Equivalent? true
Emission from 1 M(W·h): 800 kg·CO₂
*/
}
}
If you're happy about the contribution, I could add the the slightly tweaked class above to either uom-energy-demos
or probably even better the Weather & Climate Demos?
If you're happy about the contribution, I could add the the slightly tweaked class above to either
uom-energy-demos
or probably even better the Weather & Climate Demos?
I am really happy that my failed attempt can become a real demo. It shows a real power of library and its ability to adopt in multiple cases.
I feel ashamed that I haven’t found .to(WH)
before! It will be better if I will not share other code I've made to substitute it. ;-)
Great, I will push those changes in the next few days. Right now, there is a problem with Sonatype/Mavencentral, but that has nothing to do with these demos.
The 3 units:
private static interface Emission extends Quantity<Emission> {} // gas i.e CO2
private static interface EmissionMass extends Quantity<EmissionMass> {} // mass of given gas
private static interface EmissionRatio extends Quantity<EmissionRatio> {} // mass ratio for given energy
are not wrong, but they add a bit of complexity and physically it is just Mass
.
You might consider something like:
final Unit<SpecificCarbonEmission> UNIT_GRAM_CO2_PER_LITRE = Units.GRAM.divide(LITRE).asType(SpecificCarbonEmission.class);
from the CO2CarDemo
, but theoretically one could also do something like
GRAM.multiply(CO2).divide(LITRE.multiply(GASOLINE)).asType(SpecificCarbonEmission.class)
;-)
Sonatype/Mavencentral, but that has nothing to do with these demos.
I’ve tried to use central publishing plugin but it didn't work in any version and portal validation been refusing stuff nexus / implicit staging accepted. So I’ve asked to create profile in s01.oss.sonatype instance and not looked back. Sadly the old claim system seem to be gone now, am I right?
Anyhow, I’ll try to play around the emission stuff to see how much of CO2 my desktop computer produce while conducting ordered work! Cheers!
Hello, I've created some basic units which I wanted to evaluate for emission tracking calculations. Units are quite basic:
Problem I face is that my calculations work only if I specify operations using a given scale, for example:
When I use
kWh
it results in a wrong result:I thought my issue was caused by old uom lib, however it works same way with more recent releases of si-units. I suspect that I miss-used API. Can I ask for guidance/top how to define units/quantities so they become interoperable?