6
\$\begingroup\$

I do research and compare different numeric models to each other. Therefore, I want to easily switch out the numeric models in my simulations and evaluation code.

Some models work in cartesian coordinates, some in cylindrical coordinates. Some don't have a z-coordinate (yet), since they are primarily two-dimensional; some do. Also, the dimensions and orientations of the input and output vectors need to be the same. Obviously, all those differences need to be alleviated. But how do I structure this best? I find it hard to do the change before I understand how the modules would best look like.

Here are two models:

import numpy as np
from scipy.special import kn, iv

# Physics Constants
MU_0 = 4 * np.pi * 1e-7

# Cable Constants
P = 1.862  # length of cable [m] after which we have 360 turn; "Schlaglänge der Leiterwindung"
# A = 2.67e-2  # helix radius [m] = 2*A/sqrt(3) # Helgolandkabel
A = 65e-3  # helix radius [m] = 2*A/sqrt(3)   # 60kV Kabelstück
Q = 2 * np.pi * A / P

# Constants for the measurement
AMPS = 4  # peak current [A] of I * sin(omega * t)
R_inner = 139.2e-3  # in m
R_outer = 127.1e-2  # in m

# Program Constants
SIZE = 12
SIZE_Z = 37
ORDER = 5  # ORDER of bessel functions considered
FRAMES = 60


# coordinate transformation from cylindrical to cartesian coordinates
def coordinate_transform_cy2ca(r, theta, z):
    x = np.cos(theta) * r
    y = np.sin(theta) * r
    return x, y, z


# coordinate transformation back
def coordinate_transform_ca2cy(x, y, z):
    r = np.sqrt(np.square(x) + np.square(y))
    theta = np.arctan2(x, y)
    return r, theta, z


# vector transformation from cylindrical to cartesian coordinate system
def vector_transform_cy2ca(v_r, v_theta, v_z, R, T, Z):
    x = v_r * np.cos(T) - R * np.sin(T) * v_theta
    y = v_r * np.sin(T) + R * np.cos(T) * v_theta
    return x, y, v_z


# vector transformation back
def vector_transform_ca2cy(v_x, v_y, v_z, X, Y, Z):
    sq_devisor = np.square(X) + np.square(Y)
    devisor = np.sqrt(sq_devisor)
    r = v_x * X / devisor + v_y * Y / devisor
    theta = v_x * (-Y / sq_devisor) + v_y * X / sq_devisor
    return r, theta, v_z


# calculate vector component r of the magnetic field in cylinder coordinates
def calc_b_r(R, T, Z, m, current):  # equation 35
    m_1 = m
    m_0 = m - 1
    m_2 = m + 1

    eta_m = np.abs(m_1 * Q)
    eta_r_a = eta_m * R / A

    m_0_term = iv(m_0, eta_m) * kn(m_0, eta_r_a)
    m_2_term = iv(m_2, eta_m) * kn(m_2, eta_r_a)
    m_02_sum = m_0_term + m_2_term

    m_1_term = 2 * m_1 * iv(m_1, eta_m) * kn(m_1, eta_r_a)

    exp_term = np.exp((0 + 1j) * m_1 * (T - 2 * np.pi * Z / P))
    exp_product = 2 * np.pi * R * m_1 * Q / P * exp_term
    bessel_term = m_1_term + exp_product * m_02_sum

    b_r = ((0 + 1j) * 3 * MU_0 * current / (4 * np.pi * R)) * bessel_term
    return b_r


# calculate vector component Theta of the magnetic field in cylinder coordinates
def calc_b_theta(R, T, Z, m, current):
    m_1 = m
    m_0 = m - 1
    m_2 = m + 1

    eta_m = np.abs(m_1 * Q)
    eta_r_a = eta_m * R / A
    exp_term = np.exp((0 + 1j) * m_1 * (T - 2 * np.pi * Z / P))

    m_0_term = iv(m_0, eta_m) * kn(m_0, eta_r_a)
    m_2_term = iv(m_2, eta_m) * kn(m_2, eta_r_a)
    first_term = (2 * np.pi * m_1 * Q / P) * (m_0_term - m_2_term)

    mixed_term = (2 * eta_m / A) * iv(m_1, eta_m) * (kn(m_0, eta_r_a) + m_1 * kn(m_1, eta_r_a) / eta_r_a)
    second_term = mixed_term * exp_term

    bessel_term = second_term - first_term
    b_theta = (3 * MU_0 * current / (4 * np.pi)) * bessel_term
    return b_theta


# calculate vector component z of the magnetic field in cylinder coordinates
def calc_b_z(R, T, Z, m, current):
    m_1 = m
    m_0 = m - 1
    m__1 = m - 2  # the subscript "_1" is supposed to indicate A "-1"  -  its the K_ m-2  in the paper
    m_2 = m + 1

    eta_m = np.abs(m_1 * Q)
    eta_r_a = eta_m * R / A
    exp_term = np.exp((0 + 1j) * m_1 * (T - 2 * np.pi * Z / P))

    m__1_term = (eta_m / A) * iv(m_0, eta_m) * (m_1 * kn(m_0, eta_r_a) / eta_r_a + kn(m__1, eta_r_a))
    # same term as before, just two orders up
    mirror_term = (eta_m / A) * iv(m_2, eta_m) * (m_1 * kn(m_2, eta_r_a) / eta_r_a + kn(m_1, eta_r_a))

    m_0_term = iv(m_0, eta_m) * kn(m_0, eta_r_a) / R
    # same as before, just two orders up
    m_2_term = iv(m_2, eta_m) * kn(m_2, eta_r_a) / R

    m_02_term = (iv(m_0, eta_m) * kn(m_0, eta_r_a) - iv(m_2, eta_m) * kn(m_2, eta_r_a)) * m_1 / R

    bessel_term = m_0_term + m__1_term - m__1_term - mirror_term - m_02_term
    b_z = 3 * MU_0 * Q * current / (4 * np.pi) * bessel_term * exp_term
    return b_z


def main():
    r = np.arange(R_inner, R_outer, (R_outer - R_inner) / 1)  # SIZE)
    theta = np.arange(0, 2 * np.pi, 2 * np.pi / SIZE)
    z = np.arange(0, P, P / SIZE_Z)

    R, T, Z = np.meshgrid(r, theta, z)

    # these are the orders of the bessel functions
    # m is the index of the bessel funktion. ms is the list of indices
    ms = np.arange(int(-ORDER / 3) * 3 - 2, ORDER, 3)
    m_num = len(ms)

    # create the

    result_b_r = np.zeros([FRAMES, R.shape[0], R.shape[1], R.shape[2]]).astype(np.complex_)
    result_b_theta = np.zeros([FRAMES, T.shape[0], T.shape[1], T.shape[2]]).astype(np.complex_)
    result_b_z = np.zeros([FRAMES, Z.shape[0], Z.shape[1], Z.shape[2]]).astype(np.complex_)

    for frame in range(FRAMES):
        print(frame)

        #################### here the magnetic field for one time step for all the points in the mesh is calculated
        current = AMPS * np.exp(1j * frame * 2 * np.pi / FRAMES)
        b_r = np.zeros([m_num, R.shape[0], R.shape[1], R.shape[2]]).astype(np.complex_)
        b_theta = np.zeros([m_num, T.shape[0], T.shape[1], T.shape[2]]).astype(np.complex_)
        b_z = np.zeros([m_num, Z.shape[0], Z.shape[1], Z.shape[2]]).astype(np.complex_)

        # iterate over the indices of the bessel function, add them up later
        for i, m in enumerate(ms):
            b_r[i] = calc_b_r(R, T, Z, m, current)
            b_theta[i] = calc_b_theta(R, T, Z, m, current)
            b_z[i] = calc_b_z(R, T, Z, m, current)

        # this adds up the different parts resulting from the different orders of the bessel functions
        result_b_r[frame] = np.sum(b_r, axis=0)
        result_b_theta[frame] = np.sum(b_theta, axis=0)
        result_b_z[frame] = np.sum(b_z, axis=0)
    ##################### now the calculation for one point in time for all the indices of the bessel functions is complete

    # coordinate transform cylindrical to cartesian coordinates
    b_x, b_y, b_z = vector_transform_cy2ca(result_b_r, result_b_theta, result_b_z, R, T, Z)
    X, Y, Z = coordinate_transform_cy2ca(R, T, Z)

    # combine field vectors into one matrix
    result_b = np.array([b_x, b_y, b_z])


if __name__ == '__main__':
    main()

This is a model in 2D.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import rc
from typing import List, Pattern, Union, Tuple

# rc('text', usetex=True)
CURRENT_PEAK = 4.0
MU_0 = 4 * np.pi * 1e-7
CONDUCTOR_DISTANCE = 0.065
HELIX_RADIUS = CONDUCTOR_DISTANCE / np.sqrt(3)
LENGTH_OF_LAY = 1.862
Q = 2 * np.pi * HELIX_RADIUS / LENGTH_OF_LAY  # this expresses the cable specific relation between length of lay and
# conductor distance. for parallel conductors it is infinit, for strongly twisted ones it is small. It is A metric
# for how much magnetic field can leave the cable.


POINTS: np.ndarray = np.array(
    [[7.0, 0], [13.7, 0], [20.2, 0], [27.7, 0], [37, 0], [44.1, 0], [51.5, 0], [61.2, 0], [72, 0], [84.9, 0], [97, 0],
     [117.1, 0]]) * 1e-2
POINTS += np.array([10.0, 0.0]) * 1e-2  # radius of the pipe
DIPOL_POINT = np.array([0, 0])




def magnetic_dipol_field_in_point(dipol_coordinates, dipol_vector, point_coordinates):
    direction_vector = (point_coordinates - dipol_coordinates)
    direction_unit_vector = (direction_vector.T / np.linalg.norm(direction_vector, axis=1).T).T
    #    print(np.linalg.norm(direction_vector, axis=1))
    dot = dipol_vector.T * direction_unit_vector
    r = np.linalg.norm(direction_vector, axis=1)
    zähler = (3 * direction_unit_vector * dot - dipol_vector).T  # * ( np.exp(-Q*.089*r) / 1.55)
    nenner = np.power(np.linalg.norm(direction_vector, axis=1), 2.0)
    b_vector = (MU_0 / (4 * np.pi)) * zähler / nenner
    return b_vector.T


def main():
    fig, ax = plt.subplots()

    circle = plt.Circle((0, 0), radius=2.3, facecolor="none", linewidth=2, edgecolor='lightblue', alpha=0.3,
                        label=r"outer diameter of cable")
    plt.gca().add_artist(circle)

    dipol_vectors = np.array([1, 0])
    dipol_vectors = dipol_vectors / np.linalg.norm(dipol_vectors, axis=0)
    # print("dipol_vectors: ",dipol_vectors)
    dipol_vectors = dipol_vectors * CURRENT_PEAK * (CONDUCTOR_DISTANCE * np.sqrt(3) / 2) * 2

    #    res = np.zeros_like(POINTS)
    res = magnetic_dipol_field_in_point(DIPOL_POINT.T, dipol_vectors, POINTS)


if __name__ == '__main__':
    main()

I want to learn how to refactor this code into interchangeable modules. I have more models, this is just to illustrate the mess I am coming from, and I look for examples to follow, to unify my codebase.

\$\endgroup\$
8
  • \$\begingroup\$ This won't run. You haven't defined DIPOL_POINT and POINTS. \$\endgroup\$ Commented Jun 22, 2021 at 16:55
  • 2
    \$\begingroup\$ yes, i was cleaning up the code before posting it, and destroyed it while doing so. i need to update the code. - done \$\endgroup\$ Commented Jun 22, 2021 at 16:56
  • \$\begingroup\$ This is fairly opaque to me. Can you add a description matching up corresponding elements in your two models, and where they exist in the code? \$\endgroup\$ Commented Jun 23, 2021 at 2:46
  • \$\begingroup\$ I'm with Reinderien, I started writing an answer, but we'd need a little bit more detail. I understand scientific code is usually a mess ahah, but if you could also clarify what are the inputs and outputs of the code, I believe we could come up with something \$\endgroup\$ Commented Jun 23, 2021 at 15:34
  • \$\begingroup\$ @IEatBagels, I hear you, and I reworked the first module yesterday and started on the second one. The second one is harder because it is 2D (and needs to be 3D). My challenge is that I need to rethink it, and that takes time. I hope to update the second module today or tomorrow. It gets a lot clearer right away from doing so, and the parallel structures become more visible. If I knew how to pause and unpause a question, I would do so, but I will ping you guys once I am done as a crutch. \$\endgroup\$ Commented Jun 24, 2021 at 6:17

1 Answer 1

2
\$\begingroup\$

I don't understand the "interchangeable modules" question. I can't find a clear example in your code of two different approaches that are able to be substituted one for the other. I think you're off to a good start with your functions, though (a) they need type hints, and (b) the docstrings need to move to the inside of the signature.

As such, this will be a review on basic Numpy usage, plus some generic module structure.

Numpy

Don't MU_0 = 4 * np.pi * 1e-7; import this from scipy.constants.

np.sqrt(np.square(x) + np.square(y)) should instead use np.linalg.norm on an xy stack, but I do not demonstrate this because that code is unused so I can't regression-test it.

In these expressions:

x = v_r * np.cos(T) - R * np.sin(T) * v_theta
y = v_r * np.sin(T) + R * np.cos(T) * v_theta

factor out a common term for v_theta*R.

(0 + 1j) * 3 is just 3j.

The loop for i, m in enumerate(ms): should go away and be vectorised; when it is, the pre-declarations for b_r etc. can be deleted.

Every single transposition in magnetic_dipol_field_in_point can be removed so long as you preserve the trailing dimension when calling norm.

Spelling

dipol is dipole in English.

You should add translations for e.g. Kabelstück (cable segment?) Within comments, the original German can stay alongside English.

bessel should be capitalised as Bessel.

zähler and nenner variables should be renamed as numerator and denominator. For variable names we should use English only.

Tests

Add regression (and, ideally, unit) tests. I demonstrate regression tests. Since the output of your program for your given inputs is reasonably small, the easiest and most thorough approach to regression testing is an on-disc verbatim dump of arrays. These can be stored in the module. For the arrays having at most two non-singleton dimensions, use a simple text format; Numpy defaults to space-separated value. For larger arrays use .npy.

Modules

I don't have very meaningful names for these files because I don't understand the code groups logically.

The following directory list is shown relative to the inside of the module directory. Outside of the module directory, you can python -m mymodule to run the contents of __main__.py; on the inside of the module, you can perform relative from . imports.

This structure supports built-in unit test discovery.

$ find .
.
./.gitignore
./__init__.py
./two_models.py
./model_2d.py
./test.py
./__main__.py
./test_reference
./test_reference/models_x.ssv
./test_reference/models_b_vectors.npy
./test_reference/models_y.ssv
./test_reference/models_z.ssv
./test_reference/2d_b_vectors.ssv
./test_reference/2d_dipole_vectors.ssv

.gitignore

__pycache__/

__init__.py

Empty.

two_models.py

import numpy as np
from scipy.special import kn, iv
from scipy.constants import mu_0 as MU_0

# Cable Constants

# "Schlaglänge der Leiterwindung" (pitch length of the conductor winding)
P = 1.862  # length of cable [m] after which we have 360 turn;
# A = 2.67e-2  # helix radius [m] = 2*A/sqrt(3)  # Helgolandkabel (cable)
A = 65e-3  # helix radius [m] = 2*A/sqrt(3)      # 60kV Kabelstück (60kV cable section)
Q = 2*np.pi * A / P

# Constants for the measurement
AMPS = 4  # peak current [A] of I * sin(omega * t)
R_inner = 139.2e-3  # in m
R_outer = 127.1e-2  # in m

# Program Constants
SIZE = 12
SIZE_Z = 37
ORDER = 5  # ORDER of bessel functions considered
FRAMES = 60


def coordinate_transform_cy2ca(
    r: np.ndarray,      # 12,1,37
    theta: np.ndarray,  # 12,1,37
    z: np.ndarray,      # 12,1,37
) -> tuple[
    np.ndarray,  # x: 12,1,37
    np.ndarray,  # y: 12,1,37
    np.ndarray,  # z: 12,1,37
]:
    """coordinate transformation from cylindrical to cartesian coordinates"""
    x = r*np.cos(theta)
    y = r*np.sin(theta)
    return x, y, z


def coordinate_transform_ca2cy(  # unused
    x: np.ndarray,
    y: np.ndarray,
    z: np.ndarray,
) -> tuple[
    np.ndarray,  # r
    np.ndarray,  # theta
    np.ndarray,  # z
]:
    """coordinate transformation back"""
    r = np.sqrt(np.square(x) + np.square(y))  # should use np.linalg.norm on an xy stack
    theta = np.arctan2(x, y)
    return r, theta, z


def vector_transform_cy2ca(
    v_r: np.ndarray,      # 60,12,1,37
    v_theta: np.ndarray,  # 60,12,1,37
    v_z: np.ndarray,      # 60,12,1,37
    R: np.ndarray,  # 12,1,37
    T: np.ndarray,  # 12,1,37
    Z: np.ndarray,  # 12,1,37
) -> tuple[
    np.ndarray,  # x: 60,12,1,37
    np.ndarray,  # y: 60,12,1,37
    np.ndarray,  # z: 60,12,1,37
]:
    """vector transformation from cylindrical to cartesian coordinate system"""
    rvt = R*v_theta
    x = v_r*np.cos(T) - rvt*np.sin(T)
    y = v_r*np.sin(T) + rvt*np.cos(T)
    return x, y, v_z


def vector_transform_ca2cy(  # unused
    v_x: np.ndarray,
    v_y: np.ndarray,
    v_z: np.ndarray,
    X: np.ndarray,
    Y: np.ndarray,
    Z: np.ndarray,
) -> tuple[
    np.ndarray,  # r
    np.ndarray,  # theta
    np.ndarray,  # v_z
]:
    """vector transformation back"""
    sq_divisor = np.square(X) + np.square(Y)
    divisor = np.sqrt(sq_divisor)
    r = v_x*X/divisor + v_y*Y/divisor
    theta = v_x*(-Y/sq_divisor) + v_y*X/sq_divisor
    return r, theta, v_z


def calc_b_r(
    R: np.ndarray,  # 12,1,37
    T: np.ndarray,  # 12,1,37
    Z: np.ndarray,  # 12,1,37
    m: np.ndarray,  # 4,
    current: complex,
) -> np.ndarray:  # b_r: 12,1,37
    """
    calculate vector component r of the magnetic field in cylinder coordinates
    equation 35
    """
    from numpy import newaxis as na
    m = m[:, na,na,na]
    m_1 = m
    m_0 = m - 1
    m_2 = m + 1

    eta_m = np.abs(m_1 * Q)
    eta_r_a = eta_m * R / A

    m_0_term = iv(m_0, eta_m) * kn(m_0, eta_r_a)
    m_2_term = iv(m_2, eta_m) * kn(m_2, eta_r_a)
    m_02_sum = m_0_term + m_2_term

    m_1_term = 2*m_1 * iv(m_1, eta_m) * kn(m_1, eta_r_a)

    exp_term = np.exp(1j*m_1*(T - 2*np.pi*Z / P))
    exp_product = 2*np.pi*R * m_1*Q/P * exp_term
    bessel_term = m_1_term + exp_product*m_02_sum

    b_r = 3j*MU_0*current / (4*np.pi*R) * bessel_term
    return b_r


def calc_b_theta(
    R: np.ndarray,  # 12,1,37
    T: np.ndarray,  # 12,1,37
    Z: np.ndarray,  # 12,1,37
    m: np.ndarray,  # 4,
    current: complex,
) -> np.ndarray:  # b_theta: 12,1,37
    """calculate vector component Theta of the magnetic field in cylinder coordinates"""
    from numpy import newaxis as na
    m = m[:, na,na,na]
    m_1 = m
    m_0 = m - 1
    m_2 = m + 1

    eta_m = np.abs(m_1 * Q)
    eta_r_a = eta_m * R / A
    exp_term = np.exp(1j*m_1*(T - 2*np.pi*Z / P))

    m_0_term = iv(m_0, eta_m) * kn(m_0, eta_r_a)
    m_2_term = iv(m_2, eta_m) * kn(m_2, eta_r_a)
    first_term = 2*np.pi*m_1 * Q/P * (m_0_term - m_2_term)

    mixed_term = 2*eta_m/A * iv(m_1, eta_m) * (kn(m_0, eta_r_a) + m_1*kn(m_1, eta_r_a)/eta_r_a)
    second_term = mixed_term * exp_term

    bessel_term = second_term - first_term
    b_theta = 3*MU_0*current / (4*np.pi) * bessel_term
    return b_theta


def calc_b_z(
    R: np.ndarray,  # 12,1,37
    T: np.ndarray,  # 12,1,37
    Z: np.ndarray,  # 12,1,37
    m: np.ndarray,  # 4,
    current: complex,
) -> np.ndarray:  # b_z: 12,1,37
    """calculate vector component z of the magnetic field in cylinder coordinates"""
    from numpy import newaxis as na
    m = m[:, na,na,na]
    m_1 = m
    m_0 = m - 1
    m__1 = m - 2  # the subscript "_1" is supposed to indicate A "-1"  -  its the K_ m-2  in the paper
    m_2 = m + 1

    eta_m = np.abs(m_1 * Q)
    eta_r_a = eta_m*R / A
    exp_term = np.exp(1j*m_1*(T - 2*np.pi*Z/P))

    m__1_term = eta_m/A * iv(m_0, eta_m) * (m_1*kn(m_0, eta_r_a)/eta_r_a + kn(m__1, eta_r_a))
    # same term as before, just two orders up
    mirror_term = eta_m/A * iv(m_2, eta_m) * (m_1*kn(m_2, eta_r_a)/eta_r_a + kn(m_1, eta_r_a))

    m_0_term = iv(m_0, eta_m) * kn(m_0, eta_r_a)/R
    m_02_term = m_1/R * (iv(m_0, eta_m)*kn(m_0, eta_r_a) - iv(m_2, eta_m)*kn(m_2, eta_r_a))

    bessel_term = m_0_term + m__1_term - m__1_term - mirror_term - m_02_term
    b_z = 3*MU_0*Q*current / (4*np.pi) * bessel_term*exp_term
    return b_z


def main() -> tuple[
    np.ndarray,  # X
    np.ndarray,  # Y
    np.ndarray,  # Z
    np.ndarray,  # result_b
]:
    r = np.arange(R_inner, R_outer, (R_outer - R_inner))  # 0.1392
    theta = np.arange(0, 2*np.pi, 2*np.pi/SIZE)  # 12,
    z = np.arange(0, P, P/SIZE_Z)                # 37,

    R, T, Z = np.meshgrid(r, theta, z)       # each 12,1,37

    # these are the orders of the bessel functions
    # m is the index of the bessel function. ms is the list of indices
    ms = np.arange(int(-ORDER/3)*3 - 2, ORDER, 3)  # == [-5, 2, 1, 4]

    result_b_r = np.zeros((FRAMES,) + R.shape, dtype=np.complex128)      # 60,12,1,37
    result_b_theta = np.zeros((FRAMES,) + T.shape, dtype=np.complex128)  # 60,12,1,37
    result_b_z = np.zeros((FRAMES,) + Z.shape, dtype=np.complex128)      # 60,12,1,37

    frames = np.arange(FRAMES)  # 60,
    currents = AMPS * np.exp(2j*frames*np.pi / FRAMES)  # 60,

    for frame, current in zip(frames, currents):
        # here the magnetic field for one time step for all the points in the mesh is calculated

        # iterate over the indices of the Bessel function, add them up later
        # each 4,12,1,37
        b_r = calc_b_r(R, T, Z, ms, current)
        b_theta = calc_b_theta(R, T, Z, ms, current)
        b_z = calc_b_z(R, T, Z, ms, current)

        # this adds up the different parts resulting from the different orders of the bessel functions
        result_b_r[frame] = b_r.sum(axis=0)
        result_b_theta[frame] = b_theta.sum(axis=0)
        result_b_z[frame] = b_z.sum(axis=0)

    # now the calculation for one point in time for all the indices of the bessel functions is complete

    # coordinate transform cylindrical to cartesian coordinates
    # each 60,12,1,37
    b_x, b_y, b_z = vector_transform_cy2ca(result_b_r, result_b_theta, result_b_z, R, T, Z)
    # each 12,1,37
    X, Y, Z = coordinate_transform_cy2ca(R, T, Z)

    # combine field vectors into one matrix of 3,60,12,1,37
    result_b = np.stack((b_x, b_y, b_z))

    return X, Y, Z, result_b

model_2d.py

import matplotlib.pyplot as plt
import numpy as np
from scipy.constants import mu_0 as MU_0

CURRENT_PEAK = 4.
CONDUCTOR_DISTANCE = 0.065
HELIX_RADIUS = CONDUCTOR_DISTANCE/np.sqrt(3)
LENGTH_OF_LAY = 1.862

# this expresses the cable specific relation between length of lay and
# conductor distance. for parallel conductors it is infinite; for strongly twisted ones it is small. It is a metric
# for how much magnetic field can leave the cable.
Q = 2*np.pi * HELIX_RADIUS/LENGTH_OF_LAY

POINTS: np.ndarray = np.array((
    (  7.0, 0),
    ( 13.7, 0),
    ( 20.2, 0),
    ( 27.7, 0),
    ( 37,   0),
    ( 44.1, 0),
    ( 51.5, 0),
    ( 61.2, 0),
    ( 72,   0),
    ( 84.9, 0),
    ( 97,   0),
    (117.1, 0),
)) * 1e-2
POINTS += np.array((10.e-2, 0.))  # radius of the pipe
DIPOLE_POINT = np.zeros(2)


def magnetic_dipole_field_in_point(
    dipole_coords: np.ndarray,  # 2,
    dipole_vector: np.ndarray,  # 2,
    point_coordinates: np.ndarray,  # 12,2
) -> np.ndarray:  # b_vector: 12,2
    direction_vector = point_coordinates - dipole_coords  # 12,2
    r = np.linalg.norm(direction_vector, axis=1, keepdims=True)  # 12,1
    direction_unit_vector = direction_vector/r   # 12,2
    dot = dipole_vector * direction_unit_vector  # 12,2
    numerator = 3*direction_unit_vector*dot - dipole_vector  # 12,2  # * ( np.exp(-Q*.089*r) / 1.55)
    b_vector = MU_0/4/np.pi * numerator/r**2     # 12,2
    return b_vector  # 12,2


def plot() -> None:
    fig, ax = plt.subplots()

    circle = plt.Circle(
        xy=(0, 0), radius=2.3, facecolor='none', linewidth=2, edgecolor='lightblue', alpha=0.3,
        label='outer diameter of cable',
    )
    ax.add_artist(circle)


def main() -> tuple[
    np.ndarray,  # dipole vectors
    np.ndarray,  # b vector
]:
    dipole_vectors = np.array((1., 0.))
    dipole_vectors *= CURRENT_PEAK * CONDUCTOR_DISTANCE * np.sqrt(3)

    res = magnetic_dipole_field_in_point(DIPOLE_POINT, dipole_vectors, POINTS)
    return dipole_vectors, res

test.py

import pathlib
import unittest

import numpy as np

from . import model_2d, two_models


class Regression(unittest.TestCase):
    DATA_PATH = pathlib.Path(__file__).parent / 'test_reference'

    def save_reference_2d(self) -> None:
        self.DATA_PATH.mkdir(exist_ok=True)
        dipole_vectors, b_vectors = model_2d.main()
        np.savetxt(self.DATA_PATH/'2d_b_vectors.ssv', b_vectors)
        np.savetxt(self.DATA_PATH/'2d_dipole_vectors.ssv', dipole_vectors)

    def save_reference_models(self) -> None:
        x, y, z, result_b = two_models.main()
        # For text tables, drop the inner (1) dimension
        np.savetxt(self.DATA_PATH/'models_x.ssv', x.squeeze())
        np.savetxt(self.DATA_PATH/'models_y.ssv', y.squeeze())
        np.savetxt(self.DATA_PATH/'models_z.ssv', z.squeeze())
        # High-dimensional, no text possible
        np.save(self.DATA_PATH/'models_b_vectors.npy', result_b)

    def test_model_2d(self) -> None:
        dipole_vectors, b_vectors = model_2d.main()

        dipole_ref = np.loadtxt(self.DATA_PATH/'2d_dipole_vectors.ssv')
        assert np.allclose(dipole_vectors, dipole_ref, rtol=0, atol=1e-18)

        b_ref = np.loadtxt(self.DATA_PATH/'2d_b_vectors.ssv')
        assert np.allclose(b_vectors, b_ref, rtol=0, atol=1e-24)

    def test_two_models(self) -> None:
        x, y, z, result_b = two_models.main()

        x_ref = np.loadtxt(self.DATA_PATH/'models_x.ssv')[:, np.newaxis, :]
        y_ref = np.loadtxt(self.DATA_PATH/'models_y.ssv')[:, np.newaxis, :]
        z_ref = np.loadtxt(self.DATA_PATH/'models_z.ssv')[:, np.newaxis, :]
        assert np.allclose(x, x_ref, rtol=0, atol=1e-18)
        assert np.allclose(y, y_ref, rtol=0, atol=1e-18)
        assert np.allclose(z, z_ref, rtol=0, atol=1e-18)

        b_ref = np.load(self.DATA_PATH/'models_b_vectors.npy')
        assert np.allclose(result_b, b_ref, rtol=0, atol=1e-18)

__main__.py

So that your module entry point can be used with python -m.

from matplotlib import pyplot as plt
from . import two_models, model_2d

two_models.main()
model_2d.main()
plt.show()

./test_reference/models_x.ssv

1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01
1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01
6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02 6.960000000000000908e-02
8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18 8.523541722065577321e-18
-6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02 -6.959999999999996745e-02
-1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01 -1.205507362067938237e-01
-1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01
-1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01 -1.205507362067938792e-01
-6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02
-2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17 -2.557062516619673196e-17
6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02 6.959999999999989806e-02
1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01 1.205507362067938099e-01

./test_reference/models_b_vectors.npy

Binary.

./test_reference/models_y.ssv

0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00
6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02 6.959999999999998133e-02
1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01 1.205507362067938376e-01
1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01 1.391999999999999904e-01
1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01 1.205507362067938654e-01
6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02 6.960000000000003684e-02
1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17 1.704708344413115464e-17
-6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02 -6.959999999999995357e-02
-1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01 -1.205507362067938099e-01
-1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01 -1.391999999999999904e-01
-1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01 -1.205507362067939070e-01
-6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02 -6.960000000000005071e-02

./test_reference/models_z.ssv

0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00
0.000000000000000000e+00 5.032432432432432795e-02 1.006486486486486559e-01 1.509729729729729908e-01 2.012972972972973118e-01 2.516216216216216606e-01 3.019459459459459816e-01 3.522702702702703026e-01 4.025945945945946236e-01 4.529189189189189446e-01 5.032432432432433211e-01 5.535675675675676422e-01 6.038918918918919632e-01 6.542162162162162842e-01 7.045405405405406052e-01 7.548648648648649262e-01 8.051891891891892472e-01 8.555135135135135682e-01 9.058378378378378892e-01 9.561621621621622102e-01 1.006486486486486642e+00 1.056810810810810963e+00 1.107135135135135284e+00 1.157459459459459605e+00 1.207783783783783926e+00 1.258108108108108247e+00 1.308432432432432568e+00 1.358756756756756889e+00 1.409081081081081210e+00 1.459405405405405531e+00 1.509729729729729852e+00 1.560054054054054173e+00 1.610378378378378494e+00 1.660702702702702815e+00 1.711027027027027136e+00 1.761351351351351457e+00 1.811675675675675778e+00

./test_reference/2d_b_vectors.ssv

3.116492804242619336e-06 0.000000000000000000e+00
1.603493778465198396e-06 0.000000000000000000e+00
9.875295167165007170e-07 0.000000000000000000e+00
6.336964450788489057e-07 0.000000000000000000e+00
4.077258580471332231e-07 0.000000000000000000e+00
3.077297195329102525e-07 0.000000000000000000e+00
2.381297958691565211e-07 0.000000000000000000e+00
1.776658606130297121e-07 0.000000000000000000e+00
1.339480101764005530e-07 0.000000000000000000e+00
1.000072640854404068e-07 0.000000000000000000e+00
7.866769328553735901e-08 0.000000000000000000e+00
5.575359424616046055e-08 0.000000000000000000e+00

./test_reference/2d_dipole_vectors.ssv

4.503332099679080991e-01
0.000000000000000000e+00
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.