Skip to content

Commit

Permalink
fix: Implemented bugfix from CoilGen
Browse files Browse the repository at this point in the history
* Implementation for Issue #60
  • Loading branch information
kev-m committed Oct 11, 2023
1 parent 8c888e1 commit f501116
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 59 deletions.
2 changes: 1 addition & 1 deletion pyCoilGen/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Magnetic Field Coil Generator for Python."""
# Semantic Versioning according to https://semver.org/spec/v2.0.0.html
__version__ = "0.1.2" # Next: 0.1.2 Due to generalising dependencies for pip
__version__ = "0.1.3" # Patch level, due to bugfixes from CoilGen. Issue #60
42 changes: 32 additions & 10 deletions pyCoilGen/sub_functions/find_group_cut_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,38 @@ def find_group_cut_position(loop_group: TopoGroup, group_center: np.ndarray, mes
cut_point_uv = point_a_uv + (point_b_uv - point_a_uv) * cut_point_ratio
cut_position.cut_point.add_uv(cut_point_uv)

# NOTE: cut_point has shape (3,) not (1,3), i.e. Python not MATLAB convention

# Delete repeating degenerate cut points
arr_abs = np.abs(np.diff(cut_position.cut_point.uv, axis=1)) # Python convention
repeat_inds = np.where(arr_abs < 1e-10)[0]
is_repeating_cutpoint = np.any(repeat_inds)
if is_repeating_cutpoint:
cut_position.cut_point.v = np.delete(cut_position.cut_point.v, np.where(repeat_inds), axis=1)
cut_position.cut_point.uv = np.delete(cut_position.cut_point.uv, np.where(repeat_inds), axis=1)
cut_position.cut_point.segment_ind = np.delete(cut_position.cut_point.segment_ind, np.where(repeat_inds))
# NOTE: cut_position.cut_point.v has shape (n,3) i.e. Python not MATLAB convention

try:
# Delete repeating degenerate cut points
arr_abs = np.abs(np.diff(cut_position.cut_point.uv, axis=1)) # Python convention
repeat_inds = np.where(arr_abs < 1e-10)[0]
is_repeating_cutpoint = np.any(repeat_inds)
if is_repeating_cutpoint:
cut_position.cut_point.v = np.delete(cut_position.cut_point.v, np.where(repeat_inds), axis=1)
cut_position.cut_point.uv = np.delete(cut_position.cut_point.uv, np.where(repeat_inds), axis=1)
cut_position.cut_point.segment_ind = np.delete(
cut_position.cut_point.segment_ind, np.where(repeat_inds))
except ValueError as e:
log.debug("Exception: %s", e)

# https://github.com/kev-m/pyCoilGen/issues/60
# Take care of the exception that the cut plane has no intersection with the loop
if cut_position.cut_point.v is None:
max_ind = np.argmax(np.dot(loop_group.loops[loop_ind].v.T, cut_plane_direction))
min_ind = np.argmin(np.dot(loop_group.loops[loop_ind].v.T, cut_plane_direction))

# To get (n,3)
cut_position.cut_point.v = np.vstack(
(loop_group.loops[loop_ind].v[:, min_ind], loop_group.loops[loop_ind].v[:, max_ind]))
# To get (n,2)
cut_position.cut_point.uv = np.vstack(
(loop_group.loops[loop_ind].uv[:, min_ind], loop_group.loops[loop_ind].uv[:, max_ind]))

if max_ind != loop_group.loops[loop_ind].v.shape[1] - 1:
cut_position.cut_point.segment_ind = [min_ind, max_ind - 1]
else:
cut_position.cut_point.segment_ind = [min_ind, max_ind]

# Separated into higher and lower cut points:
# First: use the 2D representation of the loop
Expand Down
103 changes: 55 additions & 48 deletions scratchpad/checking1.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,67 @@
# System imports
import sys
from pathlib import Path
import numpy as np

# Trimesh
import trimesh
# System imports
import sys

# Logging
import logging

# Local imports
# Add the sub_functions directory to the Python module search path
sub_functions_path = Path(__file__).resolve().parent / '..'
sys.path.append(str(sub_functions_path))

# Import the required modules from sub_functions directory
from sub_functions.build_cylinder_mesh import build_cylinder_mesh
from sub_functions.read_mesh import create_unique_noded_mesh
from pyCoilGen.pyCoilGen_release import pyCoilGen
from pyCoilGen.sub_functions.constants import DEBUG_BASIC, DEBUG_VERBOSE

if __name__ == "__main__":
if __name__ == '__main__':
# Set up logging
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
# logging.basicConfig(level=logging.INFO)

# attach to logger so trimesh messages will be printed to console
# trimesh.util.attach_to_log()

cylinder_height = 0.8
cylinder_radius = 0.3
num_circular_divisions = 4 # 20
num_longitudinal_divisions = 3 # 20
rotation_vector_x = 1.0
rotation_vector_y = 0.0
rotation_vector_z = 0.0
rotation_angle = 0.0
data_mesh = build_cylinder_mesh(cylinder_height, cylinder_radius, num_circular_divisions,
num_longitudinal_divisions, rotation_vector_x, rotation_vector_y,
rotation_vector_z, rotation_angle)
coil_mesh = create_unique_noded_mesh(data_mesh)

#log.debug(" coil_mesh: Vertices: %s", coil_mesh.get_vertices())
#log.debug(" coil_mesh: Faces: %s", coil_mesh.get_faces())
log.debug(" shape vertices: %s", coil_mesh.get_vertices().shape)
log.debug(" faces min: %d, max: %s", np.min(coil_mesh.get_faces()), np.max(coil_mesh.get_faces()))

parts = coil_mesh.separate_into_get_parts()
log.debug("Parts: %d", len(parts))

# Access the Trimesh implementation
mesh = coil_mesh.trimesh_obj

# is the current mesh watertight?
log.debug("mesh.is_watertight: %s", mesh.is_watertight)

# what's the euler number for the mesh?
log.debug("mesh.euler_number: %s", mesh.euler_number)

mesh.show()

tikhonov_factor = 10000
num_levels = 30
pcb_width = 0.002
cut_width = 0.025
normal_shift = 0.006
min_loop_significance = 3

circular_resolution = 10
conductor_width = 0.0015
theta = np.linspace(0, 2*np.pi, circular_resolution)
cross_sectional_points = np.array([np.sin(theta), np.cos(theta)]) * conductor_width
normal_shift_smooth_factors = [5, 5, 5]

# Define the parameters as a dictionary
parameters = {
'field_shape_function': '0.2500000000000001*x + 0.7694208842938134*y + 0.5877852522924731*z',
'coil_mesh_file': 'create cylinder mesh',
'cylinder_mesh_parameter_list': [0.4913, 0.154, 50, 50, 0, 1, 0, np.pi/2],
'surface_is_cylinder_flag': True,
'min_loop_significance': min_loop_significance,
'target_region_radius': 0.1,
'levels': num_levels,
'pot_offset_factor': 0.25,
'interconnection_cut_width': cut_width,
'conductor_cross_section_width': pcb_width,
'normal_shift_length': normal_shift,
'skip_postprocessing': False,
'make_cylindrical_pcb': True,
'skip_inductance_calculation': False,
'cross_sectional_points': cross_sectional_points,
'normal_shift_smooth_factors': normal_shift_smooth_factors,
# 'smooth_flag': True,
'smooth_factor': 2,
'save_stl_flag': True,
'tikhonov_reg_factor': tikhonov_factor,

'output_directory': 'images', # [Current directory]
'project_name': 'find_group_cut_test', # See https://github.com/kev-m/pyCoilGen/issues/60
'persistence_dir': 'debug',
'debug': DEBUG_BASIC,

'sf_dest_file' : 'test_find_group_cut',
'sf_source_file' : 'test_find_group_cut'

}

# Run the algorithm with the given parameters (CoilGen function is not provided here)
result = pyCoilGen(log, parameters)

0 comments on commit f501116

Please sign in to comment.