partmor / ezaero

ezaero - Easy aerodynamics in Python :airplane:
https://ezaero.readthedocs.io
MIT License
30 stars 3 forks source link

Discuss about sweep angle when defining a wing #22

Open jorgepiloto opened 3 years ago

jorgepiloto commented 3 years ago

While working in #3, I just noticed that panels are not being generated properly since a local chord shift is being introduced:

https://github.com/partmor/ezaero/blob/a7c1f31b191ea605e9a9802c645a0ffb0c98ce08/src/ezaero/vlm/steady.py#L224-L228

This shift should be introduced only within vortex rings, not on wing panels. The bug has not been identified early since for drawing actual geometry of the wing, panel matrix was used. I implemented a geometry visualizer which does not require from a simulation to be used, only needs wing parameters:

newplot (16)

Notice how panels are not placed in proper place, they are shifted in the local chord direction. I was finally able to fix this issue, see:

newplot (17)

Now panels adapt perfectly to geometry and collocation points are 3/4 of the local chord

partmor commented 3 years ago

I've looked a bit into it, and I think there is not a bug.

Maybe the way the wing is built is a bit confusing. Let me try to break it down:

As is currently is (i.e. ignoring the -great- enhancement from #20) the wing is built using:

|-------------- y
|  A ---- B
|  |      |
|  C ---- D
|
x

Then in _build_wing_vortex_panels() I add the corresponding offset to each wing panel to obtain the vortex panel.

I think the confusing fact here is the definition of the sweep angle tied to the quarter-chord line. I think I chose that due to legacy reasons (I think it was preferred at UPM, where I studied).

If this is too unintuitive or not canon, I'm open to have a discussion and refactor this.

If you run the simple example in the examples dir, you'll see that if you look at sim.wing_panels[0, 0] and sim.wing_panels[-1, 0] the delta_x of the A point from the former, and the C point from the latter is exactly the tip_chord.

@jorgepiloto let me know if this makes sense to you :)

PS: It is true I should've documented this a bit better, also the vectorization on 4-D arrays and absence of for-loops beyond the wing building method might make seem a bit obfuscated. On the latter, I might have got too excited using vectorized NumPy and einsums to squeeze performance; maybe Numba on more naive code would've made more sense for the sake of readability? who knows... at the time I committed to vectorization ;) (also open to discussion here)

jorgepiloto commented 3 years ago

Oh! Swept angle is the one for 1/4 chord line :bulb:

You are completely right, sweep angle is defined for the 25% of the chord. However, from a building point of view and once defining a wing part, I think it is more usual to have the "leading edge sweep angle". Therefore, this is not a bug but a misunderstanding, as you pointed out. Let me change the title of the issue.

What do you think we should use when defining a geometry? I can implement a function to convert between leading edge and 25% chord sweep angles, so user inputs the one for the LE but internally the one for 25% is used, so code is kept in the same way.

Regarding vectorization, your np.einsum skills are outstanding! It took me a bit to understand those ndarray matrices, but they are just a matrix of matrices holding each one the four panel boundaries coordinates. I will be using this approach from now on in other projects, code is so fast! Thanks! :heart:

partmor commented 3 years ago

What do you think we should use when defining a geometry? I can implement a function to convert between leading edge and 25% chord sweep angles, so user inputs the one for the LE but internally the one for 25% is used, so code is kept in the same way.

This sounds super reasonable @jorgepiloto, if it's not too much extra work go for it :)

Regarding vectorization, your np.einsum skills are outstanding! It took me a bit to understand those ndarray matrices, but they are just a matrix of matrices holding each one the four panel boundaries coordinates. I will be using this approach from now on in other projects, code is so fast! Thanks! ❤️

haha! good ol' tensor Einstein summation! it's very handy to express these kind of linalg operations in a concise way. The good thing is that GPU-enabled frameworks like TensorFlow, JAX, etc. support this operation, so you have guaranteed compatibility if you are in the need of squeezing even more performance via GPU parallelization.