femagtools 1.8.3__py3-none-any.whl → 1.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- femagtools/__init__.py +1 -1
- femagtools/bch.py +10 -6
- femagtools/dxfsl/area.py +4 -1
- femagtools/dxfsl/conv.py +49 -17
- femagtools/dxfsl/converter.py +239 -75
- femagtools/dxfsl/fslrenderer.py +18 -22
- femagtools/dxfsl/functions.py +24 -2
- femagtools/dxfsl/geom.py +100 -23
- femagtools/dxfsl/machine.py +44 -7
- femagtools/dxfsl/shape.py +4 -0
- femagtools/dxfsl/symmetry.py +78 -25
- femagtools/fsl.py +0 -1
- femagtools/machine/afpm.py +2 -2
- femagtools/machine/effloss.py +2 -2
- femagtools/machine/im.py +6 -8
- femagtools/machine/sm.py +2 -2
- femagtools/mcv.py +10 -11
- femagtools/templates/mesh-airgap.mako +6 -0
- femagtools/utils.py +1 -1
- femagtools/windings.py +11 -4
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/METADATA +1 -1
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/RECORD +27 -27
- tests/test_parident.py +2 -1
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/LICENSE +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/WHEEL +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/top_level.txt +0 -0
    
        femagtools/dxfsl/geom.py
    CHANGED
    
    | @@ -2256,45 +2256,120 @@ class Geometry(object): | |
| 2256 2256 | 
             
                        return center[0]
         | 
| 2257 2257 | 
             
                    return None
         | 
| 2258 2258 |  | 
| 2259 | 
            -
                def  | 
| 2259 | 
            +
                def is_same_center(self, center_lst, center, rtol, atol):
         | 
| 2260 | 
            +
                    for c in center_lst:
         | 
| 2261 | 
            +
                        if points_are_close(c['center'], center['center'], rtol, atol):
         | 
| 2262 | 
            +
                            radius = center['radius'][0]
         | 
| 2263 | 
            +
                            if not radius in c['radius']:
         | 
| 2264 | 
            +
                                c['radius'].append(radius)
         | 
| 2265 | 
            +
                            c['count'] = c['count'] + 1
         | 
| 2266 | 
            +
                            return True
         | 
| 2267 | 
            +
                    return False
         | 
| 2268 | 
            +
             | 
| 2269 | 
            +
                def get_center_with_x(self, center_lst, x):
         | 
| 2270 | 
            +
                    c_list = [c for c in center_lst
         | 
| 2271 | 
            +
                              if np.isclose(c['center'][0], x, rtol=self.rtol, atol=self.atol)]
         | 
| 2272 | 
            +
                    if not c_list:
         | 
| 2273 | 
            +
                        return None
         | 
| 2274 | 
            +
                    cy_list = [(c['center'][1], c) for c in c_list]
         | 
| 2275 | 
            +
                    cy_list.sort()
         | 
| 2276 | 
            +
                    y, c = cy_list[0]
         | 
| 2277 | 
            +
                    return c
         | 
| 2278 | 
            +
             | 
| 2279 | 
            +
                def get_center_with_y(self, center_lst, y):
         | 
| 2280 | 
            +
                    c_list = [c for c in center_lst
         | 
| 2281 | 
            +
                              if np.isclose(c['center'][1], y, rtol=self.rtol, atol=self.atol)]
         | 
| 2282 | 
            +
                    if not c_list:
         | 
| 2283 | 
            +
                        return None
         | 
| 2284 | 
            +
                    cy_list = [(c['center'][0], c) for c in c_list]
         | 
| 2285 | 
            +
                    cy_list.sort()
         | 
| 2286 | 
            +
                    [logger.info("y=%s, c=%s", y, c) for y, c in cy_list]
         | 
| 2287 | 
            +
                    y, c = cy_list[0]
         | 
| 2288 | 
            +
                    return c
         | 
| 2289 | 
            +
             | 
| 2290 | 
            +
                def get_center_arcs(self, mm):
         | 
| 2260 2291 | 
             
                    logger.debug("begin of get_center_arcs")
         | 
| 2261 2292 | 
             
                    center_list = []
         | 
| 2293 | 
            +
                    x_min, x_max, y_min, y_max = mm
         | 
| 2294 | 
            +
             | 
| 2295 | 
            +
                    def center_is_inside(c):
         | 
| 2296 | 
            +
                        tol = 0.1
         | 
| 2297 | 
            +
                        x, y = c
         | 
| 2298 | 
            +
                        if x-tol > x_min and \
         | 
| 2299 | 
            +
                           x+tol < x_max and \
         | 
| 2300 | 
            +
                           y-tol > y_min and \
         | 
| 2301 | 
            +
                           y+tol < y_max:
         | 
| 2302 | 
            +
                            return True
         | 
| 2303 | 
            +
                        return False
         | 
| 2304 | 
            +
             | 
| 2262 2305 | 
             
                    circles = [e for e in self.elements() if is_Circle(e)]
         | 
| 2263 2306 | 
             
                    logger.debug(" -- %s Circles", len(circles))
         | 
| 2264 2307 |  | 
| 2265 2308 | 
             
                    for e in circles:
         | 
| 2266 2309 | 
             
                        center = (round(e.center[0], 3), round(e.center[1], 3))
         | 
| 2267 | 
            -
                         | 
| 2268 | 
            -
             | 
| 2310 | 
            +
                        entry = {'center': center,
         | 
| 2311 | 
            +
                                 'radius': [round(e.radius, 1)],
         | 
| 2312 | 
            +
                                 'phi': e.get_angle_of_arc(),
         | 
| 2313 | 
            +
                                 'dist': e.length(),
         | 
| 2314 | 
            +
                                 'inside': center_is_inside(center),
         | 
| 2315 | 
            +
                                 'count': 1}
         | 
| 2316 | 
            +
                        center_list.append(entry)
         | 
| 2269 2317 |  | 
| 2270 2318 | 
             
                    arcs = [e for e in self.elements() if is_Arc(e)]
         | 
| 2271 2319 | 
             
                    logger.debug(" -- %s Arcs", len(arcs))
         | 
| 2272 2320 |  | 
| 2273 2321 | 
             
                    for e in arcs:
         | 
| 2274 2322 | 
             
                        center = (round(e.center[0], 3), round(e.center[1], 3))
         | 
| 2275 | 
            -
                         | 
| 2276 | 
            -
             | 
| 2277 | 
            -
             | 
| 2278 | 
            -
             | 
| 2279 | 
            -
             | 
| 2280 | 
            -
             | 
| 2281 | 
            -
             | 
| 2282 | 
            -
             | 
| 2323 | 
            +
                        entry = {'center': center,
         | 
| 2324 | 
            +
                                 'radius': [round(e.radius, 1)],
         | 
| 2325 | 
            +
                                 'phi': e.get_angle_of_arc(),
         | 
| 2326 | 
            +
                                 'dist': e.length(),
         | 
| 2327 | 
            +
                                 'inside': center_is_inside(center),
         | 
| 2328 | 
            +
                                 'count': 1}
         | 
| 2329 | 
            +
                        if not self.is_same_center(center_list, entry, self.rtol, self.atol):
         | 
| 2330 | 
            +
                            center_list.append(entry)
         | 
| 2283 2331 |  | 
| 2284 2332 | 
             
                    center = None
         | 
| 2285 | 
            -
                    arc_list = [[ | 
| 2333 | 
            +
                    arc_list = [[c['count'], len(c['radius']), c['phi'], n, c]
         | 
| 2334 | 
            +
                                for n, c in enumerate(center_list)]
         | 
| 2286 2335 | 
             
                    arc_list.sort(reverse=True)
         | 
| 2287 2336 |  | 
| 2288 | 
            -
                     | 
| 2289 | 
            -
             | 
| 2290 | 
            -
                        center = c1[2]
         | 
| 2291 | 
            -
                        if len(arc_list) > 1:
         | 
| 2292 | 
            -
                            c2 = arc_list[1]
         | 
| 2293 | 
            -
                            if not c1[0] > c2[0]:
         | 
| 2294 | 
            -
                                center = None
         | 
| 2337 | 
            +
                    logger.debug("x min/max = %s/%s", x_min, x_max)
         | 
| 2338 | 
            +
                    logger.debug("y min/max = %s/%s", y_min, y_max)
         | 
| 2295 2339 |  | 
| 2296 | 
            -
                    logger.debug(" | 
| 2297 | 
            -
                     | 
| 2340 | 
            +
                    [logger.debug("Arc %s", arc) for arc in arc_list]
         | 
| 2341 | 
            +
                    if not arc_list:
         | 
| 2342 | 
            +
                        logger.debug("end of get_center_arcs: no arcs")
         | 
| 2343 | 
            +
                        return None
         | 
| 2344 | 
            +
             | 
| 2345 | 
            +
                    cnt, cr1, p, n, c1 = arc_list[0]
         | 
| 2346 | 
            +
                    logger.debug("First Entry: %s", c1)
         | 
| 2347 | 
            +
                    center = c1['center']
         | 
| 2348 | 
            +
                    if len(arc_list) > 1:
         | 
| 2349 | 
            +
                        cnt, cr2, p, n, c2 = arc_list[1]
         | 
| 2350 | 
            +
                        logger.debug("Second Entry: %s", c2)
         | 
| 2351 | 
            +
                        if not cr1 > cr2:
         | 
| 2352 | 
            +
                            center = None
         | 
| 2353 | 
            +
             | 
| 2354 | 
            +
                    if center:
         | 
| 2355 | 
            +
                        logger.debug("end of get_center_arcs: -> %s", center)
         | 
| 2356 | 
            +
                        return center
         | 
| 2357 | 
            +
             | 
| 2358 | 
            +
                    c_entry = self.get_center_with_x(center_list, x_min)
         | 
| 2359 | 
            +
                    if c_entry:
         | 
| 2360 | 
            +
                        center = c_entry['center']
         | 
| 2361 | 
            +
                        if center[1] < y_min:
         | 
| 2362 | 
            +
                            logger.debug("end of get_center_arcs: x -> %s", center)
         | 
| 2363 | 
            +
                            return center
         | 
| 2364 | 
            +
                    c_entry = self.get_center_with_y(center_list, y_min)
         | 
| 2365 | 
            +
                    if c_entry:
         | 
| 2366 | 
            +
                        center = c_entry['center']
         | 
| 2367 | 
            +
                        if center[0] < x_min:
         | 
| 2368 | 
            +
                            logger.debug("end of get_center_arcs: y -> %s", center)
         | 
| 2369 | 
            +
                            return center
         | 
| 2370 | 
            +
             | 
| 2371 | 
            +
                    logger.debug("end of get_center_arcs: no center found")
         | 
| 2372 | 
            +
                    return None
         | 
| 2298 2373 |  | 
| 2299 2374 | 
             
                def get_center_dim(self, mm):
         | 
| 2300 2375 | 
             
                    return (round(mm[0], 4), round(mm[2], 4))
         | 
| @@ -2305,7 +2380,9 @@ class Geometry(object): | |
| 2305 2380 | 
             
                        return None
         | 
| 2306 2381 |  | 
| 2307 2382 | 
             
                    center = None
         | 
| 2308 | 
            -
                     | 
| 2383 | 
            +
                    # Zuerst suchen wir anhand der Circle- und Arc-Segmente nach einem
         | 
| 2384 | 
            +
                    # möglichen Center-Punkt.
         | 
| 2385 | 
            +
                    center_arcs = self.get_center_arcs(mm)
         | 
| 2309 2386 |  | 
| 2310 2387 | 
             
                    if center_arcs:
         | 
| 2311 2388 | 
             
                        center = center_arcs
         | 
| @@ -3259,7 +3336,7 @@ class Geometry(object): | |
| 3259 3336 | 
             
                        max_size, max_w = windings_surface[0]
         | 
| 3260 3337 | 
             
                        for sz, w in windings_surface[1:]:
         | 
| 3261 3338 | 
             
                            logger.debug("winding size = %s", sz)
         | 
| 3262 | 
            -
                            if sz / max_size < 0. | 
| 3339 | 
            +
                            if sz / max_size < 0.70:
         | 
| 3263 3340 | 
             
                                w.set_type(AREA.TYPE_AIR)
         | 
| 3264 3341 | 
             
                                if sz / max_size < 0.2:
         | 
| 3265 3342 | 
             
                                    windings_found -= 1
         | 
    
        femagtools/dxfsl/machine.py
    CHANGED
    
    | @@ -135,6 +135,16 @@ class Machine(object): | |
| 135 135 | 
             
                    self.geom.is_outer = True
         | 
| 136 136 | 
             
                    self.geom.is_inner = False
         | 
| 137 137 |  | 
| 138 | 
            +
                def set_attributes(self,
         | 
| 139 | 
            +
                                   kind="",
         | 
| 140 | 
            +
                                   inner=False,
         | 
| 141 | 
            +
                                   outer=False):
         | 
| 142 | 
            +
                    self.set_kind(kind)
         | 
| 143 | 
            +
                    if inner:
         | 
| 144 | 
            +
                        self.set_inner()
         | 
| 145 | 
            +
                    if outer:
         | 
| 146 | 
            +
                        self.set_outer()
         | 
| 147 | 
            +
             | 
| 138 148 | 
             
                def clear_cut_lines(self):
         | 
| 139 149 | 
             
                    self.geom.clear_cut_lines()
         | 
| 140 150 | 
             
                    if self.mirror_geom is not None:
         | 
| @@ -635,9 +645,13 @@ class Machine(object): | |
| 635 645 | 
             
                    parts = symmetry.find_symmetry()  # temp solution
         | 
| 636 646 | 
             
                    logger.debug(">>> Symmetry parts = %s <<<", parts)
         | 
| 637 647 |  | 
| 638 | 
            -
                    if parts  | 
| 639 | 
            -
                         | 
| 640 | 
            -
             | 
| 648 | 
            +
                    if parts == 1:
         | 
| 649 | 
            +
                        # no slices, but ok
         | 
| 650 | 
            +
                        return False
         | 
| 651 | 
            +
             | 
| 652 | 
            +
                    found = (parts > 1)
         | 
| 653 | 
            +
             | 
| 654 | 
            +
                    if not found:
         | 
| 641 655 | 
             
                        found = self.geom.find_symmetry(self.radius,
         | 
| 642 656 | 
             
                                                        self.startangle,
         | 
| 643 657 | 
             
                                                        self.endangle,
         | 
| @@ -833,11 +847,11 @@ class Machine(object): | |
| 833 847 | 
             
                        if dist_start > dist_end:
         | 
| 834 848 | 
             
                            machine.mirror_all_areas(self.startangle)
         | 
| 835 849 | 
             
                            machine.rotate_to(angle)
         | 
| 836 | 
            -
                            machine.geom.create_list_of_areas(delete=True)
         | 
| 837 850 | 
             
                            machine.startangle -= angle
         | 
| 838 851 | 
             
                        else:
         | 
| 839 852 | 
             
                            machine.mirror_all_areas(self.endangle)
         | 
| 840 853 | 
             
                            machine.endangle += angle
         | 
| 854 | 
            +
                        machine.geom.create_list_of_areas(delete=True)
         | 
| 841 855 | 
             
                        machine.set_alfa_and_corners()
         | 
| 842 856 | 
             
                        machine.part = machine.part_of_circle()
         | 
| 843 857 | 
             
                        machine.geom.set_subregion_parameters(self.startangle,
         | 
| @@ -907,23 +921,25 @@ class Machine(object): | |
| 907 921 | 
             
                                                        first_thirdangle,
         | 
| 908 922 | 
             
                                                        second_thirdangle)
         | 
| 909 923 | 
             
                    machine_mirror_1.clear_cut_lines()
         | 
| 910 | 
            -
             | 
| 911 924 | 
             
                    machine_mirror_1.repair_hull()
         | 
| 912 925 | 
             
                    machine_mirror_1.set_alfa_and_corners()
         | 
| 926 | 
            +
                    if machine_mirror_1.geom.number_of_edges() < 2:  # very bad
         | 
| 927 | 
            +
                        logger.debug("end get_third_symmetry_mirror: no remaining elements")
         | 
| 928 | 
            +
                        return None
         | 
| 913 929 | 
             
                    if not machine_mirror_1.check_symmetry_graph(0.001, 0.05):
         | 
| 914 930 | 
             
                        logger.debug("end get_third_symmetry_mirror: no mirror first third")
         | 
| 915 931 | 
             
                        return None
         | 
| 916 932 |  | 
| 917 933 | 
             
                    if plt:
         | 
| 918 934 | 
             
                        plt.render_elements(machine_mirror_1.geom, Shape,
         | 
| 919 | 
            -
                                            title="Part",
         | 
| 935 | 
            +
                                            title="Part 1",
         | 
| 920 936 | 
             
                                            show=True,
         | 
| 921 937 | 
             
                                            with_corners=False,
         | 
| 922 938 | 
             
                                            with_nodes=False,
         | 
| 923 939 | 
             
                                            neighbors=True)
         | 
| 924 940 |  | 
| 925 941 | 
             
                        plt.render_elements(machine_mirror_1.mirror_geom, Shape,
         | 
| 926 | 
            -
                                            title="Counterpart",
         | 
| 942 | 
            +
                                            title="Counterpart 1",
         | 
| 927 943 | 
             
                                            show=True,
         | 
| 928 944 | 
             
                                            with_corners=False,
         | 
| 929 945 | 
             
                                            with_nodes=False,
         | 
| @@ -935,10 +951,28 @@ class Machine(object): | |
| 935 951 | 
             
                    machine_mirror_2.clear_cut_lines()
         | 
| 936 952 | 
             
                    machine_mirror_2.repair_hull()
         | 
| 937 953 | 
             
                    machine_mirror_2.set_alfa_and_corners()
         | 
| 954 | 
            +
                    if machine_mirror_2.geom.number_of_edges() < 2:  # very bad
         | 
| 955 | 
            +
                        logger.debug("end get_third_symmetry_mirror: no remaining elements")
         | 
| 956 | 
            +
                        return None
         | 
| 938 957 | 
             
                    if not machine_mirror_2.check_symmetry_graph(0.001, 0.05):
         | 
| 939 958 | 
             
                        logger.debug("end get_third_symmetry_mirror: no mirror second third")
         | 
| 940 959 | 
             
                        return None
         | 
| 941 960 |  | 
| 961 | 
            +
                    if plt:
         | 
| 962 | 
            +
                        plt.render_elements(machine_mirror_2.geom, Shape,
         | 
| 963 | 
            +
                                            title="Part 2",
         | 
| 964 | 
            +
                                            show=True,
         | 
| 965 | 
            +
                                            with_corners=False,
         | 
| 966 | 
            +
                                            with_nodes=False,
         | 
| 967 | 
            +
                                            neighbors=True)
         | 
| 968 | 
            +
             | 
| 969 | 
            +
                        plt.render_elements(machine_mirror_2.mirror_geom, Shape,
         | 
| 970 | 
            +
                                            title="Counterpart 2",
         | 
| 971 | 
            +
                                            show=True,
         | 
| 972 | 
            +
                                            with_corners=False,
         | 
| 973 | 
            +
                                            with_nodes=False,
         | 
| 974 | 
            +
                                            neighbors=True)
         | 
| 975 | 
            +
             | 
| 942 976 | 
             
                    machine_mirror_1.previous_machine = self
         | 
| 943 977 | 
             
                    logger.debug("end get_third_symmetry_mirror: ok")
         | 
| 944 978 | 
             
                    return machine_mirror_1
         | 
| @@ -992,6 +1026,9 @@ class Machine(object): | |
| 992 1026 | 
             
                                            with_nodes=False,
         | 
| 993 1027 | 
             
                                            neighbors=True)
         | 
| 994 1028 |  | 
| 1029 | 
            +
                    if machine_mirror.geom.number_of_edges() < 2:  # very bad
         | 
| 1030 | 
            +
                        logger.debug("end get_symmetry_mirror: no remaining elements")
         | 
| 1031 | 
            +
                        return None
         | 
| 995 1032 | 
             
                    if machine_mirror.check_symmetry_graph(0.001, 0.05):
         | 
| 996 1033 | 
             
                        machine_mirror.previous_machine = self
         | 
| 997 1034 | 
             
                        machine_mirror.rotate_to(0.0)
         | 
    
        femagtools/dxfsl/shape.py
    CHANGED
    
    | @@ -467,6 +467,10 @@ class Circle(Shape): | |
| 467 467 | 
             
                    r0 = np.linalg.norm(self.center)
         | 
| 468 468 | 
             
                    return max(abs(r-r0-self.radius), abs(r-r0+self.radius))
         | 
| 469 469 |  | 
| 470 | 
            +
                def length(self):
         | 
| 471 | 
            +
                    """returns length of this circle"""
         | 
| 472 | 
            +
                    return self.radius*2*np.pi
         | 
| 473 | 
            +
             | 
| 470 474 | 
             
                def overlapping_shape(self, e, rtol=1e-03, atol=1e-03):
         | 
| 471 475 | 
             
                    if not (isinstance(e, Arc) or isinstance(e, Circle)):
         | 
| 472 476 | 
             
                        # end overlapping_shape: Circle (not Arc or Circle)
         | 
    
        femagtools/dxfsl/symmetry.py
    CHANGED
    
    | @@ -120,7 +120,15 @@ class Symmetry(object): | |
| 120 120 | 
             
                    areas.sort(reverse=True)
         | 
| 121 121 | 
             
                    return areas
         | 
| 122 122 |  | 
| 123 | 
            +
                def get_equal_areas(self, areas):
         | 
| 124 | 
            +
                    return
         | 
| 125 | 
            +
             | 
| 123 126 | 
             
                def build_results(self, areas):
         | 
| 127 | 
            +
                    logger.debug("begin of build_results with %s areas", len(areas))
         | 
| 128 | 
            +
                    [logger.debug("#%s: alpha=%s, min=%s, max=%s",
         | 
| 129 | 
            +
                                  a.get_id(), alpha, a.min_angle, a.max_angle) for
         | 
| 130 | 
            +
                     alpha, dist, h, mid, a in areas]
         | 
| 131 | 
            +
             | 
| 124 132 | 
             
                    a0_alpha, a0_min_dist, a0_height, a0_mid_angle, a0 = areas[0]
         | 
| 125 133 | 
             
                    equal_areas = [(a0_mid_angle, a0)]
         | 
| 126 134 | 
             
                    check_rslt = []
         | 
| @@ -164,6 +172,7 @@ class Symmetry(object): | |
| 164 172 | 
             
                    rslt['area'] = a0
         | 
| 165 173 | 
             
                    rslt['areasize'] = areasize
         | 
| 166 174 | 
             
                    check_rslt.append((areasize, rslt))
         | 
| 175 | 
            +
                    logger.debug("end of build_results")
         | 
| 167 176 | 
             
                    return check_rslt
         | 
| 168 177 |  | 
| 169 178 | 
             
                def get_winding_symmetry(self, inside=False):
         | 
| @@ -246,7 +255,6 @@ class Symmetry(object): | |
| 246 255 |  | 
| 247 256 | 
             
                    check_rslt = self.build_results(areas)
         | 
| 248 257 | 
             
                    logger.debug("%s results available", len(check_rslt))
         | 
| 249 | 
            -
                    [logger.debug("Result: %s", rslt) for rslt in check_rslt]
         | 
| 250 258 |  | 
| 251 259 | 
             
                    parts, start_delta = self.get_symmetry_parts(check_rslt)
         | 
| 252 260 | 
             
                    if parts < 2:
         | 
| @@ -665,6 +673,9 @@ class Symmetry(object): | |
| 665 673 | 
             
                        m1 = m2
         | 
| 666 674 | 
             
                        d1 = d2
         | 
| 667 675 |  | 
| 676 | 
            +
                    if not mid_list:
         | 
| 677 | 
            +
                        return None
         | 
| 678 | 
            +
             | 
| 668 679 | 
             
                    logger.debug("New Mids: %s", mid_list)
         | 
| 669 680 | 
             
                    delta = positive_angle(mid_list[0] * 2)
         | 
| 670 681 | 
             
                    delta_list = [delta]
         | 
| @@ -712,6 +723,41 @@ class Symmetry(object): | |
| 712 723 | 
             
                    logger.debug("end check_first_last_difference => %s", n1 + 1)
         | 
| 713 724 | 
             
                    return n1 + 1
         | 
| 714 725 |  | 
| 726 | 
            +
                def concatenate_results(self, check_rslt):
         | 
| 727 | 
            +
                    if len(check_rslt) < 2:
         | 
| 728 | 
            +
                        return check_rslt
         | 
| 729 | 
            +
                    #   ----------
         | 
| 730 | 
            +
                    def get_slices(rslt):
         | 
| 731 | 
            +
                        if rslt['slices'] is None:
         | 
| 732 | 
            +
                            return 0
         | 
| 733 | 
            +
                        if rslt.get('startdelta', 0.0) != 0.0:
         | 
| 734 | 
            +
                            return 0
         | 
| 735 | 
            +
                        if rslt.get('halfslice', None) is not None:
         | 
| 736 | 
            +
                            return 0
         | 
| 737 | 
            +
                        return rslt['slices']
         | 
| 738 | 
            +
                    #   ------
         | 
| 739 | 
            +
                    new_rslt = []
         | 
| 740 | 
            +
                    size1, n1, rslt1 = check_rslt[0]
         | 
| 741 | 
            +
                    slices1 = get_slices(rslt1)
         | 
| 742 | 
            +
                    for size2, n2, rslt2 in check_rslt[1:]:
         | 
| 743 | 
            +
                        slices2 = get_slices(rslt2)
         | 
| 744 | 
            +
                        if slices1 > 0 and \
         | 
| 745 | 
            +
                           slices1 == slices2 and \
         | 
| 746 | 
            +
                           np.isclose(size1, size2, rtol=1e-01, atol=1e-01) and \
         | 
| 747 | 
            +
                           (rslt1.get('delta_corr', 0.0) == 0.0 or \
         | 
| 748 | 
            +
                            rslt2.get('delta_corr', 0.0) == 0.0):
         | 
| 749 | 
            +
                            # concatenate
         | 
| 750 | 
            +
                            rslt1['slices'] = None
         | 
| 751 | 
            +
                            rslt2['delta_corr'] = 0.0
         | 
| 752 | 
            +
                            rslt2['areas'] = rslt2['areas'] + rslt1['areas']
         | 
| 753 | 
            +
                            logger.debug("concatenate results(size %s)", size1)
         | 
| 754 | 
            +
                        else:
         | 
| 755 | 
            +
                            new_rslt.append((size1, n1, rslt1))
         | 
| 756 | 
            +
                        slices1, size1, n1, rslt1 = (slices2, size2, n2, rslt2)
         | 
| 757 | 
            +
             | 
| 758 | 
            +
                    new_rslt.append((size1, n1, rslt1))
         | 
| 759 | 
            +
                    return new_rslt
         | 
| 760 | 
            +
             | 
| 715 761 | 
             
                def get_symmetry_parts(self, check_rslt):
         | 
| 716 762 | 
             
                    max_size = 0
         | 
| 717 763 | 
             
                    max_areas = 0
         | 
| @@ -720,10 +766,11 @@ class Symmetry(object): | |
| 720 766 | 
             
                    self.delta_angle_corr = None
         | 
| 721 767 | 
             
                    unsure_sym = False
         | 
| 722 768 |  | 
| 723 | 
            -
                    check_rslt = [(size, n, rslt) for n, (size, rslt) in enumerate(check_rslt) | 
| 769 | 
            +
                    check_rslt = [(size, n, rslt) for n, (size, rslt) in enumerate(check_rslt)
         | 
| 770 | 
            +
                                  if rslt['slices'] is not None]
         | 
| 724 771 | 
             
                    check_rslt.sort(reverse=True)
         | 
| 725 | 
            -
                     | 
| 726 | 
            -
             | 
| 772 | 
            +
                    check_rslt = self.concatenate_results(check_rslt)
         | 
| 773 | 
            +
                    [logger.debug("Result #%s: %s, %s", n, size, rslt) for size, n, rslt in check_rslt]
         | 
| 727 774 |  | 
| 728 775 | 
             
                    rtol = 1e-3
         | 
| 729 776 | 
             
                    atol = 1e-2
         | 
| @@ -740,40 +787,46 @@ class Symmetry(object): | |
| 740 787 | 
             
                    for size, n, rslt in check_rslt:
         | 
| 741 788 | 
             
                        areas = rslt['areas']
         | 
| 742 789 | 
             
                        slices = rslt['slices']
         | 
| 790 | 
            +
                        if slices is None:
         | 
| 791 | 
            +
                            continue
         | 
| 792 | 
            +
             | 
| 743 793 | 
             
                        size = rslt['areasize']
         | 
| 744 794 | 
             
                        angle_corr = rslt.get('delta_corr', 0.0)
         | 
| 745 795 |  | 
| 746 796 | 
             
                        if rslt.get('halfslice', 0) == 1:
         | 
| 747 797 | 
             
                            halfslice.append(rslt)
         | 
| 748 798 |  | 
| 749 | 
            -
                        if slices  | 
| 750 | 
            -
                             | 
| 751 | 
            -
             | 
| 752 | 
            -
             | 
| 753 | 
            -
             | 
| 754 | 
            -
             | 
| 755 | 
            -
             | 
| 756 | 
            -
             | 
| 757 | 
            -
             | 
| 758 | 
            -
             | 
| 759 | 
            -
             | 
| 760 | 
            -
             | 
| 761 | 
            -
             | 
| 762 | 
            -
                                     | 
| 763 | 
            -
                                        without_angle_corr += areas * size
         | 
| 764 | 
            -
                                    else:
         | 
| 765 | 
            -
                                        with_angle_corr += areas * size
         | 
| 799 | 
            +
                        if slices > 0:
         | 
| 800 | 
            +
                            max_size = max(max_size, size)
         | 
| 801 | 
            +
                            max_areas = max(max_areas, areas)
         | 
| 802 | 
            +
                            max_slices = max(max_slices, slices)
         | 
| 803 | 
            +
                            missing_middles += rslt.get('missing_middles', [])
         | 
| 804 | 
            +
                            area = rslt['area']
         | 
| 805 | 
            +
                            if not (np.isclose(area.min_dist,
         | 
| 806 | 
            +
                                               self.geom.min_radius,
         | 
| 807 | 
            +
                                               rtol=1e-4, atol=1e-3) and \
         | 
| 808 | 
            +
                                    np.isclose(area.max_dist,
         | 
| 809 | 
            +
                                               self.geom.max_radius,
         | 
| 810 | 
            +
                                               rtol=1e-4, atol=1e-3)):
         | 
| 811 | 
            +
                                if rslt.get('delta_corr', 0.0) == 0.0:
         | 
| 812 | 
            +
                                    without_angle_corr += areas * size
         | 
| 766 813 | 
             
                                else:
         | 
| 767 | 
            -
                                     | 
| 814 | 
            +
                                    with_angle_corr += areas * size
         | 
| 815 | 
            +
                            else:
         | 
| 816 | 
            +
                                maybe_angle_korr += areas * size
         | 
| 817 | 
            +
             | 
| 768 818 | 
             
                    logger.debug("max size: %s,  max areas: %s", max_size, max_areas)
         | 
| 819 | 
            +
                    logger.debug("Angle-Corrections: %s Yes,  %s No, %s Maybe",
         | 
| 820 | 
            +
                                 with_angle_corr,
         | 
| 821 | 
            +
                                 without_angle_corr,
         | 
| 822 | 
            +
                                 maybe_angle_korr)
         | 
| 769 823 |  | 
| 770 | 
            -
                    logger.debug("Angle-Corrections: %s Yes,  %s No",
         | 
| 771 | 
            -
                                 with_angle_corr, without_angle_corr)
         | 
| 772 824 | 
             
                    if np.isclose(with_angle_corr, without_angle_corr):
         | 
| 773 825 | 
             
                        with_angle_corr = (maybe_angle_korr > 0)
         | 
| 774 826 | 
             
                    else:
         | 
| 775 827 | 
             
                        with_angle_corr = (with_angle_corr > without_angle_corr)
         | 
| 776 828 |  | 
| 829 | 
            +
                    #   -------------------------
         | 
| 777 830 | 
             
                    def get_halfslice_counterpart(rslt):
         | 
| 778 831 | 
             
                        if rslt.get('halfslice', 0) != 2:
         | 
| 779 832 | 
             
                            return None
         | 
| @@ -788,7 +841,7 @@ class Symmetry(object): | |
| 788 841 | 
             
                               np.isclose(alpha1, alpha2, rtol=rtol, atol=atol):
         | 
| 789 842 | 
             
                                return half
         | 
| 790 843 | 
             
                        return None
         | 
| 791 | 
            -
             | 
| 844 | 
            +
                    #   -----------
         | 
| 792 845 | 
             
                    if halfslice:
         | 
| 793 846 | 
             
                        logger.debug("%s halfslice [1] found", len(halfslice))
         | 
| 794 847 |  | 
    
        femagtools/fsl.py
    CHANGED
    
    | @@ -556,7 +556,6 @@ class Builder: | |
| 556 556 | 
             
                    if 'fsl_rotor' in conv:
         | 
| 557 557 | 
             
                        self.fsl_rotor = True
         | 
| 558 558 | 
             
                        th_props = ['']
         | 
| 559 | 
            -
                        logger.debug(model['magnet'])
         | 
| 560 559 | 
             
                        if hasattr(model, 'magnet'):
         | 
| 561 560 | 
             
                            if model['magnet'].get('thcond', 0):
         | 
| 562 561 | 
             
                                th_props = [f'rotor_density = {model["magnet"]["density"]}',
         | 
    
        femagtools/machine/afpm.py
    CHANGED
    
    | @@ -11,7 +11,7 @@ from .. import model | |
| 11 11 | 
             
            from .. import utils
         | 
| 12 12 | 
             
            from .. import windings
         | 
| 13 13 | 
             
            from .. import femag
         | 
| 14 | 
            -
            from scipy.interpolate import  | 
| 14 | 
            +
            from scipy.interpolate import make_interp_spline, RegularGridInterpolator, RectBivariateSpline
         | 
| 15 15 | 
             
            from scipy.integrate import quad
         | 
| 16 16 | 
             
            import copy
         | 
| 17 17 |  | 
| @@ -58,7 +58,7 @@ def _integrate(radius, pos, val): | |
| 58 58 |  | 
| 59 59 |  | 
| 60 60 | 
             
            def _integrate1d(radius, val):
         | 
| 61 | 
            -
                interp =  | 
| 61 | 
            +
                interp = make_interp_spline(radius, val, k=1)
         | 
| 62 62 | 
             
                def func(x):
         | 
| 63 63 | 
             
                    return interp((x))
         | 
| 64 64 | 
             
                return quad(func, radius[0], radius[-1])[0]
         | 
    
        femagtools/machine/effloss.py
    CHANGED
    
    | @@ -166,9 +166,9 @@ def _generate_mesh(n, T, nb, Tb, npoints): | |
| 166 166 | 
             
                    nmax = max(n)
         | 
| 167 167 | 
             
                    tmin, tmax = 0, max(T)
         | 
| 168 168 | 
             
                    tnum = npoints[1]
         | 
| 169 | 
            -
                tip = ip. | 
| 169 | 
            +
                tip = ip.make_interp_spline(n, T, k=1)
         | 
| 170 170 | 
             
                if nb and Tb:
         | 
| 171 | 
            -
                    tbip = ip. | 
| 171 | 
            +
                    tbip = ip.make_interp_spline(nb, Tb, k=1)
         | 
| 172 172 | 
             
                else:
         | 
| 173 173 | 
             
                    def tbip(x): return 0
         | 
| 174 174 |  | 
    
        femagtools/machine/im.py
    CHANGED
    
    | @@ -35,6 +35,9 @@ def log_interp1d(x, y, kind='cubic'): | |
| 35 35 | 
             
                logy = np.log10(yy)
         | 
| 36 36 | 
             
                lin_interp = ip.interp1d(logx, logy, kind=kind, fill_value="extrapolate")
         | 
| 37 37 | 
             
                def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz)))
         | 
| 38 | 
            +
                # TODO check replace interp1d
         | 
| 39 | 
            +
                #lin_interp = ip.make_interp_spline(logx, logy, bc_type='not-a-knot')
         | 
| 40 | 
            +
                #def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz), nu=1))
         | 
| 38 41 | 
             
                return log_interp
         | 
| 39 42 |  | 
| 40 43 |  | 
| @@ -792,15 +795,10 @@ def parident(workdir, engine, f1, u1, wdgcon, | |
| 792 795 | 
             
                tend = time.time()
         | 
| 793 796 | 
             
                logger.info("Elapsed time %d s Status %s",
         | 
| 794 797 | 
             
                            (tend-tstart), status)
         | 
| 798 | 
            +
                if any([x != 'C' for x in status]):
         | 
| 799 | 
            +
                    raise ValueError("AC simulation failed")
         | 
| 795 800 | 
             
                # collect results
         | 
| 796 | 
            -
                results = []
         | 
| 797 | 
            -
                errors = []
         | 
| 798 | 
            -
                for t in job.tasks:
         | 
| 799 | 
            -
                    if t.status == 'C':
         | 
| 800 | 
            -
                        results.append(t.get_results())
         | 
| 801 | 
            -
                    else:
         | 
| 802 | 
            -
                        logger.warning("Status %s", t.status)
         | 
| 803 | 
            -
                        results.append({})
         | 
| 801 | 
            +
                results = [t.get_results() for t in job.tasks]
         | 
| 804 802 |  | 
| 805 803 | 
             
                i1_0 = results[0]['i1_0'].tolist()
         | 
| 806 804 | 
             
                psi1_0 = results[0]['psi1_0'].tolist()
         | 
    
        femagtools/machine/sm.py
    CHANGED
    
    | @@ -187,7 +187,7 @@ def parident(workdir, engine, machine, | |
| 187 187 |  | 
| 188 188 | 
             
                if simulation['calculationMode'] == 'ld_lq_fast':
         | 
| 189 189 | 
             
                    dqpars = dict(m=3, p=b['machine']['p'],
         | 
| 190 | 
            -
                                  r1=r1,
         | 
| 190 | 
            +
                                  r1=float(r1),
         | 
| 191 191 | 
             
                                  r2=machine['rotor'].get('resistance', 1),
         | 
| 192 192 | 
             
                                  rotor_mass=rotor_mass, kfric_b=1,
         | 
| 193 193 | 
             
                                  ldq=[dict(
         | 
| @@ -434,7 +434,7 @@ class SynchronousMachine(object): | |
| 434 434 | 
             
                def iqd_tmech(self, torque, n, disp=False, maxiter=500):
         | 
| 435 435 | 
             
                    """return currents for shaft torque with minimal losses"""
         | 
| 436 436 | 
             
                    if torque > 0:
         | 
| 437 | 
            -
                        startvals = self.bounds[0][1], 0, self.bounds[-1][1]
         | 
| 437 | 
            +
                        startvals = self.bounds[0][1]/2, 0, self.bounds[-1][1]
         | 
| 438 438 | 
             
                    else:
         | 
| 439 439 | 
             
                        startvals = -self.bounds[0][1]/2, 0, self.bounds[-1][1]
         | 
| 440 440 |  | 
    
        femagtools/mcv.py
    CHANGED
    
    | @@ -12,7 +12,7 @@ import pathlib | |
| 12 12 | 
             
            import struct
         | 
| 13 13 | 
             
            import math
         | 
| 14 14 | 
             
            import numpy as np
         | 
| 15 | 
            -
             | 
| 15 | 
            +
            from scipy.interpolate import make_interp_spline
         | 
| 16 16 | 
             
            from six import string_types
         | 
| 17 17 | 
             
            import femagtools.losscoeffs as lc
         | 
| 18 18 |  | 
| @@ -99,7 +99,7 @@ def norm_pfe(B, pfe): | |
| 99 99 | 
             
                            b = list(b)
         | 
| 100 100 | 
             
                            b[-1] = Bv[n]
         | 
| 101 101 | 
             
                            n += 1
         | 
| 102 | 
            -
                    pfunc =  | 
| 102 | 
            +
                    pfunc = make_interp_spline(b, pfe[i])
         | 
| 103 103 | 
             
                    m.append([float(pfunc(x))
         | 
| 104 104 | 
             
                              for x in Bv[:n]] + [None]*(len(Bv)-n))
         | 
| 105 105 | 
             
                return Bv.tolist(), m
         | 
| @@ -168,8 +168,7 @@ def recalc_bsin(curve): | |
| 168 168 | 
             
                    if bi[0] > 0:
         | 
| 169 169 | 
             
                        bi.insert(0, 0)
         | 
| 170 170 | 
             
                        hi.insert(0, 0)
         | 
| 171 | 
            -
                    bh =  | 
| 172 | 
            -
                                     kind='cubic', assume_sorted=True)
         | 
| 171 | 
            +
                    bh = make_interp_spline(bi, hi)
         | 
| 173 172 | 
             
                    for bx in c['bi'][2:]:
         | 
| 174 173 | 
             
                        bt = bx*np.sin(2*np.pi/4/ndel*x)
         | 
| 175 174 | 
             
                        nue = np.sum(bh(bt)/bt)/ndel
         | 
| @@ -196,8 +195,7 @@ def recalc_hsin(curve): | |
| 196 195 | 
             
                    if hi[0] > 0:
         | 
| 197 196 | 
             
                        hi.insert(0, 0)
         | 
| 198 197 | 
             
                        bi.insert(0, 0)
         | 
| 199 | 
            -
                    hb =  | 
| 200 | 
            -
                                     kind='cubic', assume_sorted=True)
         | 
| 198 | 
            +
                    hb = make_interp_spline(hi, bi)
         | 
| 201 199 | 
             
                    for hx in c['hi'][2:]:
         | 
| 202 200 | 
             
                        ht = hx*np.sin(2*np.pi/4/ndel*x)
         | 
| 203 201 | 
             
                        bt = hb(ht)*np.sin(2*np.pi/4/ndel*x)
         | 
| @@ -243,11 +241,12 @@ def approx(db2, curve, ctype): | |
| 243 241 | 
             
                if ctype in (DEMCRV, MAG_AC_CRV):
         | 
| 244 242 | 
             
                    dhdbn = 0
         | 
| 245 243 | 
             
                    k = len(bi2)-1
         | 
| 246 | 
            -
                    if  | 
| 247 | 
            -
                         | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 244 | 
            +
                    if k < len(curve['bi']):
         | 
| 245 | 
            +
                        if curve['bi'][k] - curve['bi'][k-1] > 0:
         | 
| 246 | 
            +
                            dhdbn = ((curve['hi'][k] - curve['h'][k-1])
         | 
| 247 | 
            +
                                     /(curve['bi'][k] - curve['bi'][k-1]))
         | 
| 248 | 
            +
                        a.append(MUE0*dhdbn)
         | 
| 249 | 
            +
                        b.append(MUE0*curve['hi'][k] - dhdbn*curve['bi'][k])
         | 
| 251 250 | 
             
                else:
         | 
| 252 251 | 
             
                    a.append(1.0)
         | 
| 253 252 | 
             
                    b.append(MUE0*curve['hi'][-1]-curve['bi'][-1])
         | 
| @@ -44,10 +44,16 @@ if not airgap_created then | |
| 44 44 | 
             
                nc_line(r2, 0.0, x2, y2, 0.0)
         | 
| 45 45 |  | 
| 46 46 | 
             
                if m.tot_num_slot > m.num_sl_gen then
         | 
| 47 | 
            +
                  if inner_da_end == nil then
         | 
| 48 | 
            +
                    inner_da_end = inner_da_start
         | 
| 49 | 
            +
                  end
         | 
| 47 50 | 
             
                  x3, y3 = pr2c(inner_da_end, alfa)
         | 
| 48 51 | 
             
                  x4, y4 = pr2c(r1, alfa)
         | 
| 49 52 | 
             
                  nc_line(x3, y3, x4, y4, 0, 0)
         | 
| 50 53 |  | 
| 54 | 
            +
                  if outer_da_end == nil then
         | 
| 55 | 
            +
                    outer_da_end = outer_da_start
         | 
| 56 | 
            +
                  end
         | 
| 51 57 | 
             
                  x3, y3 = pr2c(outer_da_end, alfa)
         | 
| 52 58 | 
             
                  x4, y4 = pr2c(r2, alfa)
         | 
| 53 59 | 
             
                  nc_line(x3, y3, x4, y4, 0, 0)
         | 
    
        femagtools/utils.py
    CHANGED
    
    | @@ -17,7 +17,7 @@ def fft(pos, y, pmod=0): | |
| 17 17 | 
             
                else:
         | 
| 18 18 | 
             
                    #negative_periodic = np.abs(y[0] - y[-1])/np.max(y) > 1
         | 
| 19 19 | 
             
                    # count zero crossings
         | 
| 20 | 
            -
                    ypos = np.asarray(y[:-1]) > 0
         | 
| 20 | 
            +
                    ypos = np.asarray(y[:-1])-np.mean(y[:-1]) > 0
         | 
| 21 21 | 
             
                    nypos = ~ypos
         | 
| 22 22 | 
             
                    nzc = len(((ypos[:-1] & nypos[1:])
         | 
| 23 23 | 
             
                               | (nypos[:-1] & ypos[1:])).nonzero()[0])
         | 
    
        femagtools/windings.py
    CHANGED
    
    | @@ -179,10 +179,10 @@ class Winding(object): | |
| 179 179 | 
             
                        nue = n
         | 
| 180 180 | 
             
                    else:
         | 
| 181 181 | 
             
                        nue = self.kw_order(n)
         | 
| 182 | 
            -
                     | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 182 | 
            +
                    if q1 == q2:  # integral slot winding
         | 
| 183 | 
            +
                        q = self.Q/2/self.m/self.p
         | 
| 184 | 
            +
                        nuep = nue/self.p
         | 
| 185 | 
            +
                        return np.sin(nuep*np.pi/2/self.m)/q/np.sin(nuep*np.pi/2/self.m/q)
         | 
| 186 186 | 
             
                    k = 2 if self.l == 1 else 1
         | 
| 187 187 | 
             
                    a = nue*k*np.pi/self.Q*Yk
         | 
| 188 188 | 
             
                    t = self.Q//Qb
         | 
| @@ -416,6 +416,13 @@ class Winding(object): | |
| 416 416 | 
             
                         [[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)])
         | 
| 417 417 | 
             
                    # complete if not  basic winding:
         | 
| 418 418 | 
             
                    Qb = self.Q//num_basic_windings(self.Q, self.p, self.l)
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                    if not np.asarray(upper).size or not np.asarray(lower).size:
         | 
| 421 | 
            +
                        layers = 1
         | 
| 422 | 
            +
                    if layers == 1 and z[1]:
         | 
| 423 | 
            +
                        z = ([[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)],
         | 
| 424 | 
            +
                             [[d*s for s, d in zip(u, ud)] for u, ud in zip(upper, udirs)])
         | 
| 425 | 
            +
             | 
| 419 426 | 
             
                    if max([abs(n) for m in z[0] for n in m]) < Qb:
         | 
| 420 427 | 
             
                        return [[k + [-n+Qb//2 if n < 0 else -(n+Qb//2) for n in k]
         | 
| 421 428 | 
             
                                 for k in m] for m in z]
         |