-
Notifications
You must be signed in to change notification settings - Fork 2
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
Dynamic system of units #35
Comments
I am not very familiar with this, so I have some questions before I comment on the implementation side of it. If I understood you correctly, the point is to choose different base representations (one for each dimension), right? So, for example, instead of everything being converted to meters, as is currently the case in the SI definitions, it would be converted to kilometers.
(As a side note, in the upcoming version I want to improve the But if I understand you correctly, you'd like to define the scale during runtime i.e. by computing some relevant length scale of the system and then defining the unit system accordingly?
What do you mean by fuzzing these scales? Changing the scales and seeing if the output is the same as a method of testing the interface to the dimensionally-unsafe code?
That sounds reasonable to me. I assume that there would be some kind of conversion struct that specifies the factor for each dimension anyways, so that could be used to convert between what I assume will be two different |
Yeah, we'd use scales of the input (e.g., length, flow velocity) to set internal units and yes, that's what the fuzzing would be for. We use an ad-hoc fuzzing in our current computational mechanics solvers (which are mostly written in C without dimensional analysis libs) to audit dimensional consistency, but it's a blunt tool because it doesn't tell you where the problem is. I assume we end up with |
I currently can't think of a way to do this statically, but dynamically one ugly implementation strategy that I can think of is introducing some kind of global |
Your comment in #56 got me thinking about this again:
For the static version of this, I think adding a sub-expression to the
This would "only" have to add a new quantity type and add the numeric traits and methods on that quantity and probably add a single conversion method such as If I understand the requirements for dynamic systems correctly, we'd compute some quantities at runtime: let (length: Length<f32>, time: Time<f32>) = compute(); For the sake of simplicity, lets say that these are already the base dimensions of the original unit system. struct DynamicQuantity<const D: usize, S>(S);
fn main() {
let (reference_length, reference_time) = compute_reference_scales();
let constructor = Constructor { length: reference_length, time: reference_time };
let length: DynamicQuantity<...> = constructor.new(meter, 100.0);
let time: DynamicQuantity<...> = constructor.new_from_quantity(10.0 * second);
} Under the hood, this would be enabled by code which is automatically generated by the struct Constructor {
length: Length,
time: Time,
}
impl Constructor {
fn new<const D: Dimension, const M: Magnitude, S>(u: Unit<D, M>, val: S) -> DynamicQuantity<S, D>
where
S: Mul<Magnitude, Output = S>,
{
DynamicQuantity(S * M * self.conversion_factor::<D>())
}
fn new_from_quantity<const D: Dimension, S>(q: Quantity<S, D>) -> DynamicQuantity<S, D> {
DynamicQuantity(q.value_unchecked() * self.conversion_factor(D))
}
fn conversion_factor<const D: Dimension>(&self) {
// or 1 over that, who knows
self.length.powi(D.length) * self.time.powi(D.time)
}
} In this implementation, the Of course, this does not guarantee any unit safety yet. One can very easily mix two differently generated dynamic quantities with this implementation. If one needs multiple reference scales at the same time, an alternative could be to extend the Quantity type to contain a third generic argument: |
It's common in computational physics (including fluid dynamics) for a solver to transform all quantities in terms of reference scales in order to improve conditioning of matrices that will arise. This can be accomplished by choosing representative base units and parsing all user input into that system, then further operations will be zero-cost. Fuzzing these scales is also a useful technique when dimensionally-unsafe code is present (such as calls to linear algebra libraries; consider the 5x5 Jacobian matrix that would arise from differentiating the
From
implementations).Do you have thoughts about how to handle this? I don't know how to get
serde_yaml::from_str
to parse into a system of units with dynamic scales, but perhaps we could parse into SI and have conversion methods.The text was updated successfully, but these errors were encountered: