sensor_coupling = np.einsum("ijk,ij->ik", c.B_coupling(p), n)
# a = np.linalg.pinv(sensor_coupling, rcond=1e-15) @ field
ss = np.linalg.svd(sensor_coupling @ sensor_coupling.T, False, False)

# reg_exps = [0.5, 1, 2, 3, 4, 5, 6, 7, 8]
reg_exps = [1]
rel_errors = []

for reg_exp in reg_exps:
    _lambda = np.max(ss) * (10 ** (-reg_exp))
    # Laplacian in the suh basis is diagonal
    BB = sensor_coupling.T @ sensor_coupling + _lambda * (-c.laplacian) / np.max(
        abs(c.laplacian)
    )
    a = np.linalg.solve(BB, sensor_coupling.T @ field)
    s = StreamFunction(a, c)
    b_filt = sensor_coupling @ s

    rel_error = np.linalg.norm(b_filt - field) / np.linalg.norm(field)
    print("Relative error:", rel_error * 100, "%")
    rel_errors.append(rel_error)

    if PLOT:
        fig = mlab.figure(bgcolor=(1, 1, 1))
        surf = s.plot(False, figure=fig)
        surf.actor.mapper.interpolate_scalars_before_mapping = True
        surf.module_manager.scalar_lut_manager.number_of_colors = 16

        if SAVE_FIGURES:
            mlab.savefig(
                SAVE_DIR + "SUH_scalp_streamfunction.png", magnification=4, figure=fig
Exemple #2
0
#%%
# Specify spherical harmonic and calculate corresponding shielded field

beta = np.zeros(Beta1.shape[0])
# beta[7] = 1 # Gradient
beta[2] = 1  # Homogeneous

# Minimum residual
_lambda = 1e3
# Minimum energy
# _lambda=1e-3
I1inner = np.linalg.solve(C.T @ C + M * ssmax / _lambda, C.T @ beta)

I2inner = P @ I1inner

coil.s = StreamFunction(I1inner, coil)
shieldcoil.s = StreamFunction(I2inner, shieldcoil)

#%%
# Do a quick 3D plot

f = mlab.figure(None,
                bgcolor=(1, 1, 1),
                fgcolor=(0.5, 0.5, 0.5),
                size=(800, 800))

coil.s.plot(figure=f, contours=20)
shieldcoil.s.plot(figure=f, contours=20)

#%%
# Compute the field and scalar potential on an XY-plane
Exemple #3
0
    [0, 0, 1, 0],
    [0, 0, 0, 1],
]) @ np.array([
    [1, 0, 0, 0],
    [0, np.cos(T_x), -np.sin(T_x), 0],
    [0, np.sin(T_x), np.cos(T_x), 0],
    [0, 0, 0, 1],
])

c.mesh.apply_transform(rotmat)

s = np.zeros((c.basis.shape[1], ))
s[2] += 1
# s[63] += 2

s = StreamFunction(s, c)

from mayavi import mlab
from mayavi.api import Engine

engine = Engine()
engine.start()

f = mlab.figure(None,
                bgcolor=(1, 1, 1),
                fgcolor=(0.5, 0.5, 0.5),
                size=(800, 700))
s.plot(figure=f, ncolors=256)
c.plot_mesh(representation="wireframe", figure=f)

j = gradient(s.vert, c.mesh, rotated=True)
ssmax = eigvalsh(C.T @ C, M, eigvals=[M.shape[1] - 1, M.shape[1] - 1])

#%% Specify spherical harmonic and calculate corresponding shielded field
beta = np.zeros(Beta1.shape[0])
beta[7] = 1  # Gradient
# beta[2] = 1  # Homogeneous

# Minimum residual
_lambda = 1e3
# Minimum energy
# _lambda=1e-3
I1inner = np.linalg.solve(C.T @ C + M * ssmax / _lambda, C.T @ beta)

I2inner = P @ I1inner

s1 = StreamFunction(I1inner, coil1)
s2 = StreamFunction(I2inner, coil2)

# s = mlab.triangular_mesh(*mesh1.vertices.T, mesh1.faces, scalars=I1)
# s.enable_contours=True
# s = mlab.triangular_mesh(*mesh2.vertices.T, mesh2.faces, scalars=I2)
# s.enable_contours=True

B1 = CB1 @ s1
B2 = CB2 @ s2

U1 = CU1 @ s1
U2 = CU2 @ s2
#%% Plot
cc1 = scalar_contour(mesh1, mesh1.vertices[:, 2], contours=[-0.001])
cc2 = scalar_contour(mesh2, mesh2.vertices[:, 2], contours=[-0.001])
Exemple #5
0
from bfieldtools.utils import load_example_mesh

import numpy as np
from mayavi import mlab

#%%
# We create a set of wire loops by picking a single (arbitrary) surface-harmonic mode
# from a plane mesh.  Finally, we discretize the  mode into a set of wire loops, which we plot.

mesh = load_example_mesh("10x10_plane")
mesh.apply_scale(0.1)  # Downsize from 10 meters to 1 meter
N_contours = 20

sb = SuhBasis(mesh, 10)  # Construct surface-harmonics basis
sf = StreamFunction(
    sb.basis[:,
             1], sb.mesh_conductor)  # Turn single mode into a stream function
c = LineConductor(
    mesh=mesh, scalars=sf,
    N_contours=N_contours)  # Discretize the stream function into wire loops

# Plot loops for testing
c.plot_loops(origin=np.array([0, -100, 0]))

#%%
# Now, we create a shifted copy of the wire loops, and the calculate the
# mutual_inductance between two sets of line conductors

mesh2 = mesh.copy()
mesh2.vertices[:, 1] += 1
c2 = LineConductor(mesh=mesh2, scalars=sf, N_contours=N_contours)
Exemple #6
0
import mosek

coil.s, prob = optimize_streamfunctions(
    coil,
    [target_spec] + induction_spec,
    objective="minimum_inductive_energy",
    solver="MOSEK",
    solver_opts={"mosek_params": {
        mosek.iparam.num_threads: 8
    }},
)

from bfieldtools.mesh_conductor import StreamFunction

shield.induced_s = StreamFunction(shield.M_coupling @ coil.s, shield)

#%%
# Plot coil windings and target points

loops = scalar_contour(coil.mesh, coil.s.vert, N_contours=6)

# loops = [simplify_contour(loop, min_edge=1e-2, angle_threshold=2e-2, smooth=True) for loop in loops]

# loops = [loop for loop in loops if loop is not None]
if PLOT:
    f = mlab.figure(None,
                    bgcolor=(1, 1, 1),
                    fgcolor=(0.5, 0.5, 0.5),
                    size=(600, 500))
    mlab.clf()
f.scene.isometric_view()
f.scene.camera.zoom(0.95)

#%%
# Now, let's compute the effect of the shield on the field produced by the coil

# Points slightly inside the shield
d = (np.mean(np.diff(shield.mesh.vertices[shield.mesh.faces[:, 0:2]], axis=1),
             axis=0) / 10)
points = shield.mesh.vertices - d * shield.mesh.vertex_normals

# Solve equivalent stream function for the perfect linear mu-metal layer.
# This is the equivalent surface current in the shield that would cause its
# scalar magnetic potential to be constant
shield.s = StreamFunction(
    np.linalg.solve(shield.U_coupling(points),
                    coil.U_coupling(points) @ coil.s), shield)

#%%
# Plot the difference in field when taking the shield into account

f = mlab.figure(None,
                bgcolor=(1, 1, 1),
                fgcolor=(0.5, 0.5, 0.5),
                size=(800, 800))
mlab.clf()

B_target = coil.B_coupling(target_points) @ coil.s

B_target_w_shield = (coil.B_coupling(target_points) @ coil.s +
                     shield.B_coupling(target_points) @ shield.s)
        opacity=0.6,
    )


#%%
fig = mlab.figure(bgcolor=(1, 1, 1))
s0 = mlab.triangular_mesh(*shieldmesh.vertices.T,
                          shieldmesh.faces,
                          color=(0.5, 0.5, 0.5),
                          opacity=0.3)
s0.actor.property.backface_culling = False
s0.actor.property.ambient = 0.5

I_prim = np.load(
    "../publication_software/Shielded coil/biplanar_streamfunction.npy")
sprim = StreamFunction(coil.vert2inner @ I_prim, coil)
m = max(abs(sprim))
s1 = sprim.plot(False, 16, vmin=-m, vmax=m)
s2 = sprim.plot(True, 20)
s2.actor.mapper.scalar_visibility = False
s2.actor.property.line_width = 1.2
# s2 = mlab.triangular_mesh(*planemesh.vertices.T, planemesh.faces, scalars=I_prim,
#                          colormap='RdBu')
# s2.enable_contours = True
# s2.contour.filled_contours = True
# s2.contour.number_of_contours = 20
s2.actor.property.render_lines_as_tubes = True
plot_plane()
scene = s0.module_manager
scene.scene.camera.position = [
    39.154871143623325,
from bfieldtools.line_conductor import LineConductor
from bfieldtools.mesh_conductor import StreamFunction
from bfieldtools.suhtools import SuhBasis
from bfieldtools.utils import load_example_mesh

import numpy as np

###############################################
# We create a set of wire loops by picking a single (arbitrary) surface-harmonic mode
# from a plane mesh.  Finally, we discretize

mesh = load_example_mesh("10x10_plane")

sb = SuhBasis(mesh, 10)  # Construct surface-harmonics basis
sf = StreamFunction(
    sb.basis[:,
             1], sb.mesh_conductor)  #Turn single mode into a stream function
c = LineConductor(mesh=mesh,
                  scalars=sf)  # Discretize the stream function into wire loops

# Plot loops for testing
fig = c.plot_loops(origin=np.array([0, -100, 0]))

###############################################
# Now, we create a shifted copy of the wire loops, and the calculate the
# mutual_inductance between two sets of line conductors

mesh2 = mesh.copy()
mesh2.vertices[:, 1] += 1
c2 = LineConductor(mesh=mesh2, scalars=sf)
c2.plot_loops(figure=fig, origin=np.array([0, -100, 0]))