Sorry, I can't do that. I have too many types in my program. If I have to write them specific to type then I have to write too many functions or have to derive too many traits.
This way, the macro will take care of expanding it and throws an error if a specific dest doesn't have a certain type. Which can be fixed simply by adding such a attribute to the struct and initializing to zero.
Well actually, I can make them with different names but, I have a problem (beam bending) which can be solved with few implementation (lattice springs, SPH, DEM, V-model), all these have the same force computation equation (or macro).
I can definitely prepend these model names to the macro (but I think eventually it doesn't look good), but do you guys have any other ideas?
I wrote some example code shows how to go in the direction of using functions in a less terrible way. I rewrote the normal_force_dem function, as it seemed the most complex in your project.
One thing that sounds like it would be an improvement would be to treat vectors as a single object instead of working directly on coordinates. In the example, I have implemented a rudimentary 2d vector type and used it to compute the vector from the point to its neighbors.
Of course this can still be much improved. Note that one advantage of using functions is that it tells you if you have unused variables. For example I noticed that you never used that d_tz_i value that you zipped into the iterator because of a compiler warning.
pub fn normal_force_dem(particles: &mut Particles, nnps: NBS2D) {
use rayon::prelude::*;
let x = &particles.x;
let y = &particles.y;
let radius = &particles.radius;
particles.fx.par_iter_mut()
.zip(particles.fy.par_iter_mut().enumerate())
.for_each(|(d_fx_i, (i, d_fy_i))|
{
let nbrs = nnps.get_neighbours(x[i], y[i]);
for j in nbrs {
let point_coord = Vector2::new(x[i], y[i]);
let neigh_coord = Vector2::new(x[j], y[j]);
let delta = neigh_coord - point_coord;
// unit vector passing from d_idx to s_idx
if let Some(unit_vector) = delta.unit_vector() {
// find overlap amount
let overlap = radius[i] + radius[j] - delta.size();
// println!("distance is {}", dist);
// println!("overlap is {}", overlap);
let kn = 1e5;
if overlap > 0. {
*d_fx_i -= kn * overlap * unit_vector.x;
*d_fy_i -= kn * overlap * unit_vector.y;
// This could have been:
// *force -= kn * overlap * unit_vector;
}
}
}
});
}
Ignoring XY problem and just answering the OP question: macros defined in the current crate get #[macro_export]-ed at the root namespace, name-clashing as you noticed.
There is a hacky way to go around this limitation:
Define your macros in a new crate, that your current crate will depend on (i.e., a helper / internals crate), using custom internal names that do not clash / collide with each other.
For instance, in your ::__helper__ crate you define:
equations_make_forces_torques_zero!, and
equations2_make_forces_torques_zero!
Within your main crate, you just reexport these macros from the right modules and with the option to rename them as you please:
pub
mod equations {
pub
use ::__helper__::equations_make_forces_torques_zero
as make_forces_torques_zero
;
}
pub
mod equations2 {
pub
use ::__helper__::equations2_make_forces_torques_zero
as make_forces_torques_zero
;
}
Thanks for the efforts. I have a question here, I was defining the variables at the top because I am inside the for loop, so by defining them mutably at the top, helps not redefining them in the loop, does this makes sense?
You can do this with a single crate as well! You just have to live with both having names at the root and reexported at the module path.
pub mod a {
#[macro_export] #[doc(hidden)]
macro_rules! __a__make_forces { }
#[doc(inline)]
pub use __a__make_forces as make_forces;
}
pub mod b {
#[macro_export] #[doc(hidden)]
macro_rules! __b__make_forces { }
#[doc(inline)]
pub use __b__make_forces as make_forces;
}
If the macro just has to be crate-local, you can skip the #[macro_export] and do pub(crate) use. (Disclaimer: while I've used this technique before I don't know how it interacts with docs, as I used this for macro-generated macros that didn't have docs.)