Skip to content

Commit 5766e23

Browse files
Fem testing (#1)
* loop-loop test * sdfsdf * fix test * add FEM test magnet-loop * replace mesh with meshing * interface + test update * adjust force output shape
1 parent 07bd0ed commit 5766e23

File tree

9 files changed

+392
-130
lines changed

9 files changed

+392
-130
lines changed

magpylib_force/__init__.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
from magpylib_force.force import getFTcube
2-
from magpylib_force.force import getFTwire
1+
from magpylib_force.force import getFT
32

43
"""
54
The magpylib-force package sits on top of magpylib for force computation
65
"""
76

87
# module level dunders
9-
__version__ = "0.1.6"
8+
__version__ = "0.1.8"
109
__author__ = "SAL"
1110
__all__ = [
12-
"getFTcube",
13-
"getFTwire",
11+
"getFT",
1412
]

magpylib_force/force.py

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,77 @@
11
import numpy as np
22
import magpylib as magpy
3-
from magpylib_force.mesh import mesh_cuboid
3+
from magpylib_force.meshing import mesh_cuboid
44
from magpylib_force.utility import check_input_anchor
5-
from magpylib_force.utility import check_input_targets_Cuboid
6-
from magpylib_force.utility import check_input_targets_Polyline
5+
from magpylib_force.utility import check_input_targets
6+
from magpylib._src.obj_classes.class_current_Polyline import Polyline
7+
from magpylib._src.obj_classes.class_magnet_Cuboid import Cuboid
8+
9+
10+
def getFT(sources, targets, anchor=None, eps=1e-5, squeeze=True):
11+
"""
12+
Compute force and torque between sources and targets.
13+
SI units are assumed for all inputs and outputs.
14+
15+
Parameters
16+
----------
17+
sources: source and collection objects or 1D list thereof
18+
Sources that generate the magnetic field. Can be a single source (or collection)
19+
or a 1D list of l sources and/or collection objects.
20+
21+
targets: single object or 1D list of t objects that are in [Cuboid, Polyline]
22+
Force and Torque acting on targets in the magnetic field generated by the sources
23+
will be computed. A target must have a valid `meshing` parameter.
24+
25+
eps: float, default=1e-5
26+
For magnet-targets the magnetic field gradient is computed using finite
27+
differences (FD). `eps` is the FD step size. A good value
28+
is 1e-5 * characteristic system size (magnet size, distance between sources
29+
and targets, ...).
30+
31+
anchor: array_like, default=None
32+
The Force adds to the Torque via the anchor point. For a freely floating magnet
33+
this would be the barycenter. If `anchor=None`, this part of the Torque computation
34+
is ommitted.
35+
36+
squeeze: bool, default=True
37+
The output of the computation has the shape (n,3) where n corresponds to the number
38+
of targets. By default this is reduced to (3,) when there is only one target.
39+
40+
Returns
41+
-------
42+
Force-Torque as ndarray of shape (2,3), of (t,2,3) when t targets are given
43+
"""
44+
anchor = check_input_anchor(anchor)
45+
targets = check_input_targets(targets)
46+
# MISSING: allow Collections
47+
48+
n = len(targets)
49+
50+
cuboids, order_cub = [], []
51+
polylines, order_poly = [], []
52+
for i,t in enumerate(targets):
53+
if isinstance(t, Cuboid):
54+
cuboids.append(t)
55+
order_cub.append(i)
56+
elif isinstance(t, Polyline):
57+
polylines.append(t)
58+
order_poly.append(i)
59+
60+
FT = np.zeros((n, 2, 3))
61+
if cuboids:
62+
FT_cube = getFTcube(sources, cuboids, eps=eps, anchor=anchor, squeeze=False)
63+
FT_cube = np.swapaxes(FT_cube, 0, 1)
64+
for ft,o in zip(FT_cube, order_cub):
65+
FT[o] = ft
66+
if polylines:
67+
FT_poly = getFTwire(sources, polylines, anchor=anchor, squeeze=False)
68+
FT_poly = np.swapaxes(FT_poly, 0, 1)
69+
for ft,o in zip(FT_poly, order_poly):
70+
FT[o] = ft
71+
#FT = np.swapaxes(FT, 0, 1)
72+
if squeeze:
73+
return np.squeeze(FT)
74+
return FT
775

876

977
def getFTcube(sources, targets, eps=1e-5, anchor=None, squeeze=True):
@@ -18,7 +86,7 @@ def getFTcube(sources, targets, eps=1e-5, anchor=None, squeeze=True):
1886
1987
targets: Cuboid object or 1D list of Cuboid objects
2088
Force and Torque acting on targets in the magnetic field generated by the sources
21-
will be computed. A target must have a valid mesh parameter.
89+
will be computed. A target must have a valid `meshing` parameter.
2290
2391
eps: float, default=1e-5
2492
The magnetic field gradient is computed using finite differences (FD). eps is
@@ -34,15 +102,12 @@ def getFTcube(sources, targets, eps=1e-5, anchor=None, squeeze=True):
34102
The output of the computation has the shape (n,3) where n corresponds to the number
35103
of targets. By default this is reduced to (3,) when there is only one target.
36104
"""
37-
anchor = check_input_anchor(anchor)
38-
targets = check_input_targets_Cuboid(targets)
39-
# MISSING: allow Collections
40105

41106
# number of Cuboids
42107
tgt_number = len(targets)
43108

44109
# number of instances of each Cuboid
45-
inst_numbers = np.array([np.prod(tgt.mesh) for tgt in targets])
110+
inst_numbers = np.array([np.prod(tgt.meshing) for tgt in targets])
46111

47112
# total number of instances
48113
no_inst = np.sum(inst_numbers)
@@ -85,7 +150,7 @@ def getFTcube(sources, targets, eps=1e-5, anchor=None, squeeze=True):
85150
F = np.squeeze(F)
86151
T = np.squeeze(T)
87152

88-
return F, T
153+
return np.array((F, T))
89154

90155

91156

@@ -96,21 +161,17 @@ def getFTwire(sources, targets, anchor=None, squeeze=True):
96161
info:
97162
targets = Polyline objects
98163
segements = linear segments within Polyline objects
99-
instances = computation instances, each segment is split into `mesh` points
164+
instances = computation instances, each segment is split into `meshing` points
100165
"""
101166

102-
anchor = check_input_anchor(anchor)
103-
targets = check_input_targets_Polyline(targets)
104-
# MISSING: allow Collections
105-
106167
# number of Polylines
107168
tgt_number = len(targets)
108169

109170
# segments of each Polyline
110171
seg_numbers = np.array([len(tgt.vertices)-1 for tgt in targets])
111172

112173
# number of mesh-points of each Polyline
113-
mesh_numbers = np.array([tgt.mesh for tgt in targets])
174+
mesh_numbers = np.array([tgt.meshing for tgt in targets])
114175

115176
# number of instances of each Polyline
116177
inst_numbers = seg_numbers*mesh_numbers
@@ -152,7 +213,7 @@ def getFTwire(sources, targets, anchor=None, squeeze=True):
152213
T = np.cross(anchor - POSS, F)
153214
T = np.array([np.sum(T[insti[i]:insti[i+1]],axis=0) for i in range(tgt_number)])
154215
else:
155-
T = np.zeros((tgt_number,))
216+
T = np.zeros((tgt_number,3))
156217

157218
# sumup force for every target
158219
F = np.array([np.sum(F[insti[i]:insti[i+1]],axis=0) for i in range(tgt_number)])
@@ -162,4 +223,4 @@ def getFTwire(sources, targets, anchor=None, squeeze=True):
162223
F = np.squeeze(F)
163224
T = np.squeeze(T)
164225

165-
return F, T
226+
return np.array((F, T))

magpylib_force/mesh.py renamed to magpylib_force/meshing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def mesh_cuboid(object):
99
returns grid positions relative to cuboid position
1010
"""
1111
a,b,c = object.dimension
12-
n1,n2,n3 = object.mesh
12+
n1,n2,n3 = object.meshing
1313
xs = np.linspace(-a/2, a/2, n1+1)
1414
ys = np.linspace(-b/2, b/2, n2+1)
1515
zs = np.linspace(-c/2, c/2, n3+1)
@@ -52,7 +52,7 @@ def mesh_cuboid_old2(object, verbose=False):
5252
grid positions: np.ndarray shape (m,3)
5353
"""
5454
a,b,c = object.dimension
55-
splitting = object.mesh
55+
splitting = object.meshing
5656
if isinstance(splitting, (float, int)):
5757
x = (a*b*c/splitting)**(1/3)
5858
n1 = m.ceil(a/x)

magpylib_force/utility.py

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,37 @@ def check_input_anchor(anchor):
1818
return anchor
1919

2020

21-
def check_input_targets_Cuboid(targets):
21+
def check_input_targets(targets):
2222
""" check and format targets input """
23-
if isinstance(targets, Cuboid):
24-
targets = [targets]
2523
if not isinstance(targets, list):
26-
raise ValueError("Bad targets input.")
24+
targets = [targets]
25+
for t in targets:
26+
if not isinstance(t, (Cuboid, Polyline)):
27+
raise ValueError(
28+
"Bad `targets` input for getFT."
29+
" `targets` can only be Cuboids and Polylines."
30+
f" Instead receivd type {type(t)} target."
31+
)
32+
if not hasattr(t, "meshing"):
33+
raise ValueError(
34+
"Bad `targets` input for getFT."
35+
" `targets` must have the `meshing` parameter set."
36+
)
2737
return targets
2838

39+
# def check_input_targets_Cuboid(targets):
40+
# """ check and format targets input """
41+
# if isinstance(targets, Cuboid):
42+
# targets = [targets]
43+
# if not isinstance(targets, list):
44+
# raise ValueError("Bad targets input.")
45+
# return targets
2946

30-
def check_input_targets_Polyline(targets):
31-
""" check and format targets input """
32-
if isinstance(targets, Polyline):
33-
targets = [targets]
34-
if not isinstance(targets, list):
35-
raise ValueError("Bad targets input.")
36-
return targets
47+
48+
# def check_input_targets_Polyline(targets):
49+
# """ check and format targets input """
50+
# if isinstance(targets, Polyline):
51+
# targets = [targets]
52+
# if not isinstance(targets, list):
53+
# raise ValueError("Bad targets input.")
54+
# return targets

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
magpylib>=5.0.1
1+
magpylib>=5.0.1

0 commit comments

Comments
 (0)