Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example is requested for python #13

Open
Steffen-W opened this issue Oct 19, 2023 · 2 comments
Open

Example is requested for python #13

Steffen-W opened this issue Oct 19, 2023 · 2 comments

Comments

@Steffen-W
Copy link

Hi @shredEngineer ,

your project looks good,
can you give me an example of how I can calculate an air coil without the gui but only via python?

I would really appreciate it

@shredEngineer
Copy link
Owner

shredEngineer commented Oct 20, 2023

Hey Steffen,

thanks for the kind words.

MagnetiCalc is very monolithic in that regard; putting all needed classes (SamplingVolume, Wire, BiotSavart, ...) together in a minimal example would take some work which I have not done yet.

All I can do right now is to give you MagnetiCalc v1.0 which is at least all in one file, but it also has some extra stuff in there, and it does NOT use any optimization, so it all runs on one core, without any speedups:

# (C) <mailto:anfrage@paulwilhelm.de>
import numpy as np
import matplotlib.pyplot as plt

# Parametrisierung und Anzeige
animation = False       # Automatische 3D-Rotation
azim, elev = 270, 90    # Anfängliche 3D-Rotation
loops = 2               # Anzahl der Schleifen
radius = 2              # Radius der Gesamtschleife
height = 3              # Höhe einer Schleife
points = False          # Zeige nummerierte Schleifenpunkte
components = True       # Zeige die Komponenten der Parametrisierung der einzelnen Schleife
slicing = 16            # Elemente der Gesamtschleife in noch kleinere Segmente zerlegen
grid = True             # Koordinatensystem anzeigen

# Berechnung der magnetischen Flussdichte
I_DC = .25              # Stromstärke
B_box = 5               # "Radius" (halbe Seitenlänge) des zu berechnenden (kubischen) Volumens (zentriert um Nullpunkt)
B_res = 151             # Auflösung des Gitters
B_normalize = True      # Vektoren normalisieren
B_scale = .15           # Skalierung der Vektoren
B_alpha = 1.0           # Sichtbarkeit der Vektoren
B_limit = 100           # Vektoren mit größerem Betrag werden darauf begrenzt

torus = True            # Begrenze Feldberechnung auf einen Torus:
torus_shell_min = 1.5   # Radius der inneren Kugelschale
torus_shell_max = 2.5   # Radius der äußeren Kugelschale
torus_z_min = 0         # Untere Z-Ebene
torus_z_max = 0         # Obere Z-Ebene

# Parametrisierung der einzelnen Schleife
#              0  1  2  3  4  5  6  7  8  9 10 11
x = -np.array([0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3]) / 3 + 1/2
y = -np.array([0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0]) + 1/2
z = +np.array([0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0]) - 1/2
p = np.linspace(0, 1, len(x))

# Erzeuge die gewünschte Anzahl Schleifen mit vorgegebenem Radius (Gesamtschleife), schließe die Gesamtschleife
X, Y, Z = [], [], []
for a in np.linspace(0, 2 * np.pi, loops, endpoint=False):
    X = np.append(X, x * np.cos(a) - (y + radius) * np.sin(a))
    Y = np.append(Y, x * np.sin(a) + (y + radius) * np.cos(a))
    Z = np.append(Z, z * height)
X, Y, Z = np.append(X, X[0]), np.append(Y, Y[0]), np.append(Z, Z[0])
P = np.linspace(0, 1, len(X))

# Linienelemente der Gesamtschleife in noch kleinere Segmente zerlegen, schließe die Gesamtschleife
nX, nY, nZ = [], [], []
for i in range(len(P) - 1):
    p1 = np.array([X[i], Y[i], Z[i]])               # Startpunkt dieses Elements
    p2 = np.array([X[i + 1], Y[i + 1], Z[i + 1]])   # Endpunkt dieses Elements
    dI = p2 - p1                                    # Linienelement
    for j in range(slicing):
        nX = np.append(nX, X[i] + dI[0] * j / slicing)
        nY = np.append(nY, Y[i] + dI[1] * j / slicing)
        nZ = np.append(nZ, Z[i] + dI[2] * j / slicing)
X, Y, Z = np.append(nX, nX[0]), np.append(nY, nY[0]), np.append(nZ, nZ[0])
P = np.linspace(0, 1, len(X))

# Zeige Matplotlib-Fenster
fig = plt.figure(
    "MagnetiCalc-v1.0: Magnetic flux density calculation example <mailto:anfrage@paulwilhelm.de>  ::  Drücke [q] zum Beenden",
    figsize=(12 if components else 6, 6)
)

if components:
    # Zeige die Komponenten der Parametrisierung der einzelnen Schleife
    ax_x = fig.add_subplot(322); ax_x.set(xlabel="$p$", ylabel="$x(p)$"); ax_x.plot(p, x); ax_x.scatter(p, x)
    ax_y = fig.add_subplot(324); ax_y.set(xlabel="$p$", ylabel="$y(p)$"); ax_y.plot(p, y); ax_y.scatter(p, y)
    ax_z = fig.add_subplot(326); ax_z.set(xlabel="$p$", ylabel="$z(p)$"); ax_z.plot(p, z); ax_z.scatter(p, z)

# Zeige die Gesamtschleife
ax_3d = fig.add_subplot(121 if components else 111, projection='3d', proj_type='ortho')
ax_3d.set(xlabel="$x$", ylabel="$y$", zlabel="$z$")
ax_3d.set_title(f"Radius = {radius}, Loops = {loops}", y=-0.086)
ax_3d.plot(X, Y, Z, c="r")

if not grid:
    # Verstecke das Koordinatensystem
    ax_3d.set_axis_off()

if points:
    # Zeige nummerierte Schleifenpunkte
    ax_3d.scatter(X, Y, Z)
    for i in range(len(P)):
        ax_3d.text(X[i], Y[i], Z[i], i)

# Berechne magnetische Flussdichte
side = np.linspace(-B_box, B_box, B_res)    # Koordinaten einer Gitterkante

# Erzeuge flaches Array der 3D-Gitterkoordinaten (Vektoren) und der Feldvektoren an jeder Gitterkoordinate
G, B = [], []
for gx in range(B_res):
    print(f"{100 * (gx + 1) / B_res:.2f} %")
    for gy in range(B_res):
        for gz in range(B_res):
            g = np.array([side[gx], side[gy], side[gz]])

            if torus:
                # Überspringe alle Punkte, die nicht auf Kreisscheiben in der XY-Ebene liegen
                g_dist = np.linalg.norm(np.array([side[gx], side[gy]]))
                if g_dist < torus_shell_min or g_dist > torus_shell_max:
                    continue

                # Überspringe alle Punkte, die nicht zwischen zwei Z-Ebenen liegen
                if g[2] < torus_z_min or g[2] > torus_z_max:
                    continue

            B_tot = np.zeros(3)  # Vektorieller Akkumulator

            # Iteriere über die Punkte der Gesamtschleife (allerletzter Punkt = allererster Punkt)
            for i in range(len(P) - 1):

                # Berechne Linienelement dI
                p1 = np.array([X[i], Y[i], Z[i]])               # Startpunkt dieses Elements
                p2 = np.array([X[i + 1], Y[i + 1], Z[i + 1]])   # Endpunkt dieses Elements
                dI = p2 - p1                                    # Linienelement
                m = p1 + dI / 2                                 # Mittelpunkt des Linienelements

                # Vektor und Abstand vom Mittelpunkt des Linienelements zur Gitterkoordinate
                R = g - m
                r = np.linalg.norm(R)

                # Berechne Flussdichteelement dB (Biot-Savart)
                dB = I_DC * np.cross(dI, R) / (r ** 3)

                # Vektorielle Superposition
                B_tot += dB

            # Betrag des gesamten Vektors
            B_mag = np.linalg.norm(B_tot)

            # Vektorlänge hart begrenzen
            if B_mag > B_limit:
                B_tot = B_tot / B_mag * B_limit

            # Speichere Koordinate und Feldvektor
            G.append(g)
            B.append(B_tot)

# Transponiere Gitter und Feld
Gx, Gy, Gz = [g[0] for g in G], [g[1] for g in G], [g[2] for g in G]
Bx, By, Bz = [b[0] for b in B], [b[1] for b in B], [b[2] for b in B]

# Zeige den Vektor der magnetischen Flussdichte an jeder Koordinate des 3D-Gitters
ax_3d.quiver(Gx, Gy, Gz, Bx, By, Bz, pivot="middle", length=B_scale, normalize=B_normalize, alpha=B_alpha)

# Erfrische Matplotlib-Fenster
plt.tight_layout()
figManager = plt.get_current_fig_manager()
figManager.window.showMaximized()

# Automatische 3D-Rotation
if animation:
    while plt.fignum_exists(fig.number):
        ax_3d.view_init(elev, azim)
        # azim += 1
        elev -= 1
        plt.draw()
        plt.pause(.001)
else:
    ax_3d.view_init(elev, azim)
    plt.show()

Let me know if this helps! :)

@Steffen-W
Copy link
Author

Hi @shredEngineer,

Thanks a lot the code looks really good. I will have a closer look and try it out the day after tomorrow. I would like to determine the inductance but in principle I can calculate the integral with the help of the field strength in space. That is facilitated with the code in any case. Thanks a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants