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
« 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]
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.
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":
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.
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))
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.
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`.
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))