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

[request] Example using Eigen #301

Open
rconde01 opened this issue Oct 14, 2021 · 7 comments
Open

[request] Example using Eigen #301

rconde01 opened this issue Oct 14, 2021 · 7 comments
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Milestone

Comments

@rconde01
Copy link

The documentation says this "Even though mp-units library does not implement any Linear Algebra types it is generic enough to be used with other Linear Algebra libraries existing on the market.". A set of examples using Eigen would be helpful. Blaze would probably be good too, but personally I don't use it so it's a lower priority for me.

@mpusz
Copy link
Owner

mpusz commented Oct 14, 2021

Sure, I do not have any experience with Eigen so if you can contribute some examples it would be great. For now, we only have examples basing on the Linear Algebra proposal for C++ (https://mpusz.github.io/units/use_cases/linear_algebra.html).

@mpusz mpusz added enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed labels Oct 14, 2021
@dwith-ts
Copy link

dwith-ts commented Oct 14, 2021

For Eigen, full support for (uniform) physical units / quantities as scalar type is not working out of the box, it seems you have to define several traits for multiplications.
https://stackoverflow.com/questions/43477416/custom-type-matrix-int-in-eigen

Even with this, multiplication is not possible as the resulting scalar type is not identical to the input types.
For getting multiplication working, full automatic return type deduction would be needed which is not supported in Eigen as far as I know.

Your question was mainly asking for a solution for the simple(r) case of uniform units in vector, so I am not sure whether my talk on a full-blown solution is interesting for you. I’ll mention it anyways:
https://m.youtube.com/watch?v=J6H9CwzynoQ

@PatrickKa
Copy link

Is there any update on this? I would love to use mp-units and Eigen for my project at work. Unfortunately, I am still new to both, so any help to get started would be greatly appreciated.

I took a look at test/runtime/linear_algebra_test.cpp and just replaced the vector type with one from Eigen. This allows me to create a position_vector but I cannot do scalar multiplication or vector addition (see Compiler Explorer). @dwith-ts already mentioned that one needs to define additional things for that to work, but the referenced question on stackoverflow is still unanswered. Since I am also completely new to Eigen, I didn't get around to really dig into their documentation for that kind of info yet, so it would be nice if someone can point me in the right direction.

BTW, we are also not set on using Eigen. In case Blaze, Armadillo, or some other library plays nicer with mp-units we are open to switch to that, so any usage examples with a decently mature linear algebra library are welcome as well.

@mpusz
Copy link
Owner

mpusz commented Jul 12, 2024

Hi, I plan to extend vector and tensor quantities support for the 2.4.0 release. First, I have to finish other things for 2.3.0.

@dwith-ts's use cases are quite extreme (e.g., Kalman filters), which would be awesome to support, but I do not know any linear algebra library that allows this out of the box. There are, however, two simpler cases here that we want to address first. I would like to understand which one you are interested in:

  1. "Parallelizing" the work by doing operations on a vector or matrix of quantities (e.g., vector of mass). With this, you are basically doing many scalar operations at once.
  2. Modeling vector and tensor quantities (e.g., position vector, velocity, acceleration, force, etc).

For the second use case, there are two ways to model it:

2a. Vector of quantities

Linear algebra type takes quantity as a representation type and does basic arithmetic operations on them (+, -, *, /) while calculating things like dot or cross product. This is supported by all of the libraries on the market but is quite incorrect and not safe. In this scenario, physical quantities library can't determine a proper quantity type as it does not know if dot or cross product is being calculated.

2b. Quantity with vector as a representation type (aka. vector quantity)

In this case, the physical quantities library is in charge of performing LA operations and knows their precise results. This is not supported by any library on the market besides Pint. mp-units is meant to support it in 2.4.0 release.

Please let me know which scenarios you are interested in (I mean all the users here, not just @PatrickKa). We want some feedback on how you would like to use our library.

Now, coming back to @PatrickKa code example, I must admit that I never used Eigen or Blaze as well. It is surprising to me to see that Eigen uses expression templates, which means that scalar * vector does not return vector. In your case Eigen::CwiseBinaryOp<Eigen::internal::scalar_product_op<double, double>, const Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, const Eigen::Matrix<double, 3, 1, 0, 3, 1> >, const Eigen::Matrix<double, 3, 1, 0, 3, 1> > was returned. This type is not recognized as a vector representation type by the mp-units as no is_vector type trait was specialized for it. I tried to do it here https://godbolt.org/z/e9qYdWMrv, but I found another issue. The resulting type is not regular, which is a current requirement of mp-units for representation types. I am not sure what to do with it :-(

@PatrickKa
Copy link

Thx for the fast reply. I am dealing with position, velocity, ... in 3D space, so I am interested in scenario 2. Yes, a general approach with more abstract vectors composed of different quantities would be great, and something that might come up at work in the future. For now, however, all my vectors have uniform units.

From the two subscenarios you described, I would prefer 2b, because I think that better represents the "real" thing. As you pointed out already, a vector is more than just a collection of, in my case, three scalars. It supports different operations and a quantity library needs to know about those (Force ⋅ distance = energy, but force × distance = torque). However, since support for that is further in the future (and I need something to work with now) I am also very much open to 2a. Unfortunately, I don't know if it works easily enough (or at all). For example, Armadillo does not support custom scalar types. Eigen does, but it seems to be tricky to get it to work with mp-units, because it uses expression templates (I am not surprised by that because AFAIU that's what pretty much every linear algebra library does for performance reasons).

In the meantime, I also found this talk by @chiphogg from CppCon2021 where, starting at 42:50, he also talks about Eigen and units. He mentions that given a type T Eigen assumes that T * T → T which is obviously wrong as soon as quantities are involved. It seems like the customization points that Eigen provides are not enough to fix this, and you need to patch Eigen itself. This is completely out of scope for me, though. He then goes on to suggest a different approach. And as I am looking up the corresponding issue in the Au library I see that you commented there as well, so you already know 😅.

In conclusion, I am very much looking forward to version 2.4.0 of this amazing library. Until that is released, I will play around some more with Eigen, or give Blaze a try to make scenario 2a work. I don't have high hopes for that, though. If it turns out to be too troublesome, or it takes too long, I can still use mp-units to improve my interfaces but then use .numerical_value_in() to do the actual calculations just with doubles.

@mpusz
Copy link
Owner

mpusz commented Jul 12, 2024

Thanks for sharing your thoughts and use cases.

I think that independently from trying to make mp-units work with Eigen, Blaze, or other libraries, we should provide our own simple vector and tensor types for up to 3 dimensions together with all operations required by ISQ for physics.

It shouldn't be a big task. I do not expect such handwritten operations to be slower than the ones provided by general-purpose LA libraries. Having those would greatly help in starting the work on this subject. If someone would like to implement those, please let me know. I just created #594 for this.

@mpusz
Copy link
Owner

mpusz commented Jul 12, 2024

BTW, C++26 will provide an LA engine based on BLAS (https://en.cppreference.com/w/cpp/header/linalg). A reference implementation can be found here: https://github.com/kokkos/stdBLAS. It is not perfect for our needs as it does not provide owning types that we need for our use cases (mentioned in the previous post).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants