Coverage for dragonfly_sim/utils/postprocessor_utils.py: 50%

14 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-17 03:37 +0000

1def cross_2D(x, y): 

2 return x[0] * y[1] - x[1] * y[0] 

3 

4 

5def moment_integrand(force_vec, lever_vec, dimensions): 

6 """ 

7 The pitching-moment integrand: the component of (lever x force) about the 

8 axis the aerofoil/wing pitches around. 

9 

10 This exists because cross_2D above is a genuinely 2D expression -- 

11 x[0]*y[1] - x[1]*y[0] reads only components 0 and 1 -- so applying it 

12 unchanged to 3D vectors silently returns the moment about the VERTICAL 

13 axis (a yawing moment) rather than the pitching moment. The two coordinate 

14 conventions in use here disagree about which index is "vertical": 

15 

16 2D: x = chordwise, y = vertical 

17 -> the pitch axis is z, and cross_2D(force, lever) is that 

18 component (up to the sign convention baked into compute_cm). 

19 3D: x = chordwise, y = spanwise, z = vertical 

20 (see the mesh note at the top of wing_opt.py) 

21 -> the pitch axis is y, i.e. (lever x force)_y = r_z*F_x - r_x*F_z. 

22 

23 The 2D branch returns exactly the previous expression, so 2D results are 

24 unchanged bit-for-bit. 

25 """ 

26 if dimensions == 2: 

27 return cross_2D(force_vec, lever_vec) 

28 elif dimensions == 3: 

29 return lever_vec[2]*force_vec[0] - lever_vec[0]*force_vec[2] 

30 else: 

31 raise ValueError( 

32 "moment_integrand supports 2 or 3 dimensions, got {}".format(dimensions)) 

33 

34 

35def moment_about(force_vec, lever_vec, direction, dimensions): 

36 """ 

37 The component along `direction` of the moment (lever x force), the 

38 integrand of the moment of a wall force density about a point: 

39 M = d . (r x F), right-hand rule. 

40 

41 3D: the full cross product, projected on the (unit) direction vector. 

42 2D: the only nonzero component of r x F is the out-of-plane one, 

43 r_x F_y - r_y F_x, times the z entry of `direction`. 

44 

45 `direction` is a UFL-compatible vector of 3 entries in both cases (a 

46 dolfinx Constant, say); in 2D only its z entry is read. The 

47 nose-up-positive pitching moment of moment_integrand is direction 

48 (0, 1, 0) in 3D and (0, 0, -1) in 2D. 

49 """ 

50 if dimensions == 2: 

51 return direction[2]*(lever_vec[0]*force_vec[1] - lever_vec[1]*force_vec[0]) 

52 elif dimensions == 3: 

53 return (direction[0]*(lever_vec[1]*force_vec[2] - lever_vec[2]*force_vec[1]) 

54 + direction[1]*(lever_vec[2]*force_vec[0] - lever_vec[0]*force_vec[2]) 

55 + direction[2]*(lever_vec[0]*force_vec[1] - lever_vec[1]*force_vec[0])) 

56 else: 

57 raise ValueError( 

58 "moment_about supports 2 or 3 dimensions, got {}".format(dimensions))