Coupling sims work
This commit is contained in:
parent
cc59a6567e
commit
4ea1b26293
3 changed files with 352 additions and 85 deletions
72
Untitled.ipynb
Normal file
72
Untitled.ipynb
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -108,10 +108,15 @@ def elmer_solver(cwd, stdout_log=None, stderr_log=None):
|
|||
return result
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.group()
|
||||
def cli():
|
||||
pass
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('-d', '--sim-dir', type=click.Path(dir_okay=True, file_okay=False, path_type=Path))
|
||||
@click.argument('mesh_file', type=click.Path(dir_okay=False, path_type=Path))
|
||||
def run_capacitance_simulation(mesh_file, sim_dir):
|
||||
def self_capacitance(mesh_file, sim_dir):
|
||||
physical = dict(enumerate_mesh_bodies(mesh_file))
|
||||
if sim_dir is not None:
|
||||
sim_dir = Path(sim_dir)
|
||||
|
|
@ -168,10 +173,10 @@ def run_capacitance_simulation(mesh_file, sim_dir):
|
|||
|
||||
capacitance_matrix = np.loadtxt(tmpdir / 'capacitance.txt')
|
||||
|
||||
@click.command()
|
||||
@cli.command()
|
||||
@click.option('-d', '--sim-dir', type=click.Path(dir_okay=True, file_okay=False, path_type=Path))
|
||||
@click.argument('mesh_file', type=click.Path(dir_okay=False, path_type=Path))
|
||||
def run_inductance_simulation(mesh_file, sim_dir):
|
||||
def inductance(mesh_file, sim_dir):
|
||||
physical = dict(enumerate_mesh_bodies(mesh_file))
|
||||
|
||||
if sim_dir is not None:
|
||||
|
|
@ -264,16 +269,149 @@ def run_inductance_simulation(mesh_file, sim_dir):
|
|||
elif P is None or R is None or U_mag is None:
|
||||
raise click.ClickException(f'Error during solver execution. Electrical parameters could not be calculated. See log files for details:\n{solver_stdout.absolute()}\n{solver_stderr.absolute()}')
|
||||
|
||||
U = math.sqrt(P*R)
|
||||
V = math.sqrt(P*R)
|
||||
I = math.sqrt(P/R)
|
||||
L = 2*U_mag / (I**2)
|
||||
|
||||
assert math.isclose(U, 1.0, abs_tol=1e-3)
|
||||
assert math.isclose(V, 1.0, abs_tol=1e-3)
|
||||
|
||||
print(f'Total magnetic field energy: {format_si(U_mag, "J")}')
|
||||
print(f'Reference coil current: {format_si(I, "Ω")}')
|
||||
print(f'Coil resistance calculated by solver: {format_si(R, "Ω")}')
|
||||
print(f'Inductance calucated from field: {format_si(L, "H")}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_inductance_simulation()
|
||||
@cli.command()
|
||||
@click.option('-r', '--reference-field', type=float, required=True)
|
||||
@click.option('-d', '--sim-dir', type=click.Path(dir_okay=True, file_okay=False, path_type=Path))
|
||||
@click.argument('mesh_file', type=click.Path(dir_okay=False, path_type=Path))
|
||||
def mutual_inductance(mesh_file, sim_dir, reference_field):
|
||||
physical = dict(enumerate_mesh_bodies(mesh_file))
|
||||
|
||||
if sim_dir is not None:
|
||||
sim_dir = Path(sim_dir)
|
||||
sim_dir.mkdir(exist_ok=True)
|
||||
|
||||
sim = elmer.load_simulation('3D_steady', 'coil_mag_sim.yml')
|
||||
mesh_dir = '.'
|
||||
mesh_fn = 'mesh'
|
||||
sim.header['Mesh DB'] = f'"{mesh_dir}" "{mesh_fn}"'
|
||||
sim.constants.update({
|
||||
'Permittivity of Vacuum': str(constants.epsilon_0),
|
||||
'Gravity(4)': f'0 -1 0 {constants.g}',
|
||||
'Boltzmann Constant': str(constants.Boltzmann),
|
||||
'Unit Charge': str(constants.elementary_charge)})
|
||||
|
||||
air = elmer.load_material('air', sim, 'coil_mag_materials.yml')
|
||||
ro4003c = elmer.load_material('ro4003c', sim, 'coil_mag_materials.yml')
|
||||
copper = elmer.load_material('copper', sim, 'coil_mag_materials.yml')
|
||||
|
||||
solver_current = elmer.load_solver('Static_Current_Conduction', sim, 'coil_mag_solvers.yml')
|
||||
solver_magdyn = elmer.load_solver('Magneto_Dynamics', sim, 'coil_mag_solvers.yml')
|
||||
solver_magdyn_calc = elmer.load_solver('Magneto_Dynamics_Calculations', sim, 'coil_mag_solvers.yml')
|
||||
|
||||
copper_eqn = elmer.Equation(sim, 'copperEqn', [solver_current, solver_magdyn, solver_magdyn_calc])
|
||||
air_eqn = elmer.Equation(sim, 'airEqn', [solver_magdyn, solver_magdyn_calc])
|
||||
|
||||
bdy_trace1 = elmer.Body(sim, 'trace1', [physical['trace1'][1]])
|
||||
bdy_trace1.material = copper
|
||||
bdy_trace1.equation = copper_eqn
|
||||
|
||||
bdy_trace2 = elmer.Body(sim, 'trace2', [physical['trace2'][1]])
|
||||
bdy_trace2.material = copper
|
||||
bdy_trace2.equation = copper_eqn
|
||||
|
||||
bdy_sub1 = elmer.Body(sim, 'substrate1', [physical['substrate1'][1]])
|
||||
bdy_sub1.material = ro4003c
|
||||
bdy_sub1.equation = air_eqn
|
||||
|
||||
bdy_sub2 = elmer.Body(sim, 'substrate2', [physical['substrate2'][1]])
|
||||
bdy_sub2.material = ro4003c
|
||||
bdy_sub2.equation = air_eqn
|
||||
|
||||
|
||||
bdy_ab = elmer.Body(sim, 'airbox', [physical['airbox'][1]])
|
||||
bdy_ab.material = air
|
||||
bdy_ab.equation = air_eqn
|
||||
|
||||
bdy_if_top1 = elmer.Body(sim, 'interface_top1', [physical['interface_top1'][1]])
|
||||
bdy_if_top1.material = copper
|
||||
bdy_if_top1.equation = copper_eqn
|
||||
|
||||
bdy_if_bottom1 = elmer.Body(sim, 'interface_bottom1', [physical['interface_bottom1'][1]])
|
||||
bdy_if_bottom1.material = copper
|
||||
bdy_if_bottom1.equation = copper_eqn
|
||||
|
||||
bdy_if_top2 = elmer.Body(sim, 'interface_top2', [physical['interface_top2'][1]])
|
||||
bdy_if_top2.material = copper
|
||||
bdy_if_top2.equation = copper_eqn
|
||||
|
||||
bdy_if_bottom2 = elmer.Body(sim, 'interface_bottom2', [physical['interface_bottom2'][1]])
|
||||
bdy_if_bottom2.material = copper
|
||||
bdy_if_bottom2.equation = copper_eqn
|
||||
|
||||
potential_force = elmer.BodyForce(sim, 'electric_potential', {'Electric Potential': 'Equals "Potential"'})
|
||||
bdy_trace1.body_force = potential_force
|
||||
bdy_trace2.body_force = potential_force
|
||||
|
||||
# boundaries
|
||||
boundary_airbox = elmer.Boundary(sim, 'FarField', [physical['airbox_surface'][1]])
|
||||
boundary_airbox.data['Electric Infinity BC'] = 'True'
|
||||
|
||||
boundary_vplus1 = elmer.Boundary(sim, 'Vplus1', [physical['interface_top1'][1]])
|
||||
boundary_vplus1.data['Potential'] = 1.0
|
||||
boundary_vplus1.data['Save Scalars'] = True
|
||||
|
||||
boundary_vminus1 = elmer.Boundary(sim, 'Vminus1', [physical['interface_bottom1'][1]])
|
||||
boundary_vminus1.data['Potential'] = 0.0
|
||||
|
||||
boundary_vplus2 = elmer.Boundary(sim, 'Vplus2', [physical['interface_top2'][1]])
|
||||
boundary_vplus2.data['Potential'] = 1.0
|
||||
boundary_vplus2.data['Save Scalars'] = True
|
||||
|
||||
boundary_vminus2 = elmer.Boundary(sim, 'Vminus2', [physical['interface_bottom2'][1]])
|
||||
boundary_vminus2.data['Potential'] = 0.0
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
tmpdir = sim_dir if sim_dir else Path(tmpdir)
|
||||
|
||||
sim.write_startinfo(tmpdir)
|
||||
sim.write_sif(tmpdir)
|
||||
# Convert mesh from gmsh to elemer formats. Also scale it from 1 unit = 1 mm to 1 unit = 1 m (SI units)
|
||||
elmer_grid(mesh_file.absolute(), 'mesh', cwd=tmpdir, scale=[1e-3, 1e-3, 1e-3],
|
||||
stdout_log=(tmpdir / 'ElmerGrid_stdout.log'),
|
||||
stderr_log=(tmpdir / 'ElmerGrid_stderr.log'))
|
||||
solver_stdout, solver_stderr = (tmpdir / 'ElmerSolver_stdout.log'), (tmpdir / 'ElmerSolver_stderr.log')
|
||||
res = elmer_solver(tmpdir,
|
||||
stdout_log=solver_stdout,
|
||||
stderr_log=solver_stderr)
|
||||
|
||||
P, R, U_mag = None, None, None
|
||||
solver_error = False
|
||||
for l in res.stdout.splitlines():
|
||||
if (m := re.fullmatch(r'StatCurrentSolve:\s*Total Heating Power\s*:\s*([0-9.+-Ee]+)\s*', l)):
|
||||
P = float(m.group(1))
|
||||
elif (m := re.fullmatch(r'StatCurrentSolve:\s*Effective Resistance\s*:\s*([0-9.+-Ee]+)\s*', l)):
|
||||
R = float(m.group(1))
|
||||
elif (m := re.fullmatch(r'MagnetoDynamicsCalcFields:\s*ElectroMagnetic Field Energy\s*:\s*([0-9.+-Ee]+)\s*', l)):
|
||||
U_mag = float(m.group(1))
|
||||
elif re.fullmatch(r'IterSolve: Linear iteration did not converge to tolerance', l):
|
||||
solver_error = True
|
||||
|
||||
if solver_error:
|
||||
raise click.ClickException(f'Error: One of the solvers did not converge. See log files for details:\n{solver_stdout.absolute()}\n{solver_stderr.absolute()}')
|
||||
elif P is None or R is None or U_mag is None:
|
||||
raise click.ClickException(f'Error during solver execution. Electrical parameters could not be calculated. See log files for details:\n{solver_stdout.absolute()}\n{solver_stderr.absolute()}')
|
||||
|
||||
V = math.sqrt(P*R)
|
||||
I = math.sqrt(P/R)
|
||||
Lm = (U_mag - 2*reference_field) / ((I/2)**2)
|
||||
|
||||
assert math.isclose(V, 1.0, abs_tol=1e-3)
|
||||
|
||||
print(f'Mutual inductance calucated from field: {format_si(Lm, "H")}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli()
|
||||
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ def traces_to_gmsh(traces, mesh_out, bbox, model_name='gerbonara_board', log=Tru
|
|||
occ = gmsh.model.occ
|
||||
eps = 1e-6
|
||||
|
||||
board_thickness -= 2*copper_thickness
|
||||
|
||||
gmsh.initialize()
|
||||
gmsh.model.add('gerbonara_board')
|
||||
if log:
|
||||
|
|
@ -144,19 +142,32 @@ def traces_to_gmsh(traces, mesh_out, bbox, model_name='gerbonara_board', log=Tru
|
|||
print('Writing')
|
||||
gmsh.write(str(mesh_out))
|
||||
|
||||
@contextmanager
|
||||
def model_delta():
|
||||
import gmsh
|
||||
gmsh.model.occ.synchronize()
|
||||
entities = {i: set() for i in range(4)}
|
||||
for dim, tag in gmsh.model.getEntities():
|
||||
entities[dim].add(tag)
|
||||
|
||||
def traces_to_gmsh_mag(traces, mesh_out, bbox, model_name='gerbonara_board', log=True, copper_thickness=0.035, board_thickness=0.8, air_box_margin_h=30.0, air_box_margin_v=80.0):
|
||||
yield
|
||||
|
||||
gmsh.model.occ.synchronize()
|
||||
new_entities = {i: set() for i in range(4)}
|
||||
for dim, tag in gmsh.model.getEntities():
|
||||
new_entities[dim].add(tag)
|
||||
|
||||
for i, dimtype in enumerate(['points', 'lines', 'surfaces', 'volumes']):
|
||||
delta = entities[i] - new_entities[i]
|
||||
print(f'Removed {dimtype} [{len(delta)}]: {", ".join(map(str, delta))[:180]}')
|
||||
|
||||
delta = new_entities[i] - entities[i]
|
||||
print(f'New {dimtype} [{len(delta)}]: {", ".join(map(str, delta))[:180]}')
|
||||
|
||||
|
||||
def _gmsh_coil_inductance_geometry(traces, mesh_out, bbox, copper_thickness, board_thickness, air_box_margin_h):
|
||||
import gmsh
|
||||
occ = gmsh.model.occ
|
||||
eps = 1e-6
|
||||
|
||||
board_thickness -= 2*copper_thickness
|
||||
|
||||
gmsh.initialize()
|
||||
gmsh.model.add('gerbonara_board')
|
||||
if log:
|
||||
gmsh.logger.start()
|
||||
|
||||
trace_tags = []
|
||||
trace_ends = set()
|
||||
render_cache = {}
|
||||
|
|
@ -218,35 +229,8 @@ def traces_to_gmsh_mag(traces, mesh_out, bbox, model_name='gerbonara_board', log
|
|||
(_dim, toplevel_tag), = tags
|
||||
|
||||
(x1, y1), (x2, y2) = bbox
|
||||
#print('first disk', first_disk)
|
||||
#print('bbox', [occ.getBoundingBox(2, tag) for tag in first_disk[1]])
|
||||
#print('last disk', last_disk)
|
||||
#print('bbox', [occ.getBoundingBox(2, tag) for tag in last_disk[1]])
|
||||
|
||||
first_geom = traces[0][0]
|
||||
#contact_tag_top = occ.addCylinder(first_geom.start.x, first_geom.start.y, copper_thickness, 0, 0, copper_thickness, first_geom.width/2)
|
||||
#contact_tag_bottom = occ.addCylinder(first_geom.start.x, first_geom.start.y, -board_thickness-copper_thickness, 0, 0, -copper_thickness, first_geom.width/2)
|
||||
|
||||
@contextmanager
|
||||
def model_delta():
|
||||
occ.synchronize()
|
||||
entities = {i: set() for i in range(4)}
|
||||
for dim, tag in gmsh.model.getEntities():
|
||||
entities[dim].add(tag)
|
||||
|
||||
yield
|
||||
|
||||
occ.synchronize()
|
||||
new_entities = {i: set() for i in range(4)}
|
||||
for dim, tag in gmsh.model.getEntities():
|
||||
new_entities[dim].add(tag)
|
||||
|
||||
for i, dimtype in enumerate(['points', 'lines', 'surfaces', 'volumes']):
|
||||
delta = entities[i] - new_entities[i]
|
||||
print(f'Removed {dimtype} [{len(delta)}]: {", ".join(map(str, delta))[:180]}')
|
||||
|
||||
delta = new_entities[i] - entities[i]
|
||||
print(f'New {dimtype} [{len(delta)}]: {", ".join(map(str, delta))[:180]}')
|
||||
|
||||
with model_delta():
|
||||
print('Fragmenting disks')
|
||||
|
|
@ -254,45 +238,34 @@ def traces_to_gmsh_mag(traces, mesh_out, bbox, model_name='gerbonara_board', log
|
|||
interface_tag_bottom = occ.addDisk(first_geom.start.x, first_geom.start.y, -board_thickness, first_geom.width/2, first_geom.width/2)
|
||||
occ.fragment([(3, toplevel_tag)], [(2, interface_tag_top), (2, interface_tag_bottom)], removeObject=True, removeTool=True)
|
||||
|
||||
#occ.synchronize()
|
||||
#_, toplevel_adjacent = gmsh.model.getAdjacencies(3, toplevel_tag)
|
||||
|
||||
#x0, y0, w = traces[0][0].start.x, traces[0][0].start.y, traces[0][0].width
|
||||
#print(x0, y0, w)
|
||||
#in_bbox = occ.getEntitiesInBoundingBox(x0-w/2-eps, y0-w/2-eps, -board_thickness-eps, x0+w/2+eps, y0+w/2+eps, eps, dim=1)
|
||||
#print('in bbox', in_bbox)
|
||||
#for dim, tag in in_bbox:
|
||||
# print(tag, 'adjacent', gmsh.model.getAdjacencies(dim, tag))
|
||||
|
||||
#print('fragment', occ.fragment([(2, tag) for tag in toplevel_adjacent], [(2, interface_tag_top), (2, interface_tag_bottom)]))
|
||||
|
||||
substrate = occ.addBox(x1, y1, -board_thickness, x2-x1, y2-y1, board_thickness)
|
||||
|
||||
x1, y1 = x1-air_box_margin_h, y1-air_box_margin_h
|
||||
x2, y2 = x2+air_box_margin_h, y2+air_box_margin_h
|
||||
w, d = x2-x1, y2-y1
|
||||
z0 = -board_thickness-air_box_margin_v
|
||||
ab_h = board_thickness + 2*air_box_margin_v
|
||||
airbox = occ.addBox(x1, y1, z0, w, d, ab_h)
|
||||
|
||||
occ.synchronize()
|
||||
|
||||
#trace_surface = gmsh.model.getBoundary([(3, toplevel_tag)], oriented=False)
|
||||
#print('Fragmenting trace surface')
|
||||
#with model_delta():
|
||||
# print(occ.fragment(trace_surface, [(2, interface_tag_top), (2, interface_tag_bottom)], removeObject=True, removeTool=False))
|
||||
|
||||
#print('Fragmenting trace')
|
||||
#with model_delta():
|
||||
# print(occ.fragment([(3, toplevel_tag)], [(3, contact_tag_top), (3, contact_tag_bottom)], removeObject=True, removeTool=False))
|
||||
|
||||
print('cut')
|
||||
with model_delta():
|
||||
print(occ.cut([(3, substrate)], [(3, toplevel_tag)], removeObject=True, removeTool=False))
|
||||
|
||||
#print('Fragmenting substrate')
|
||||
#with model_delta():
|
||||
# print(occ.fragment([(3, substrate)], [(3, toplevel_tag), (3, contact_tag_top), (3, contact_tag_bottom)], removeObject=True, removeTool=False))
|
||||
return toplevel_tag, interface_tag_top, interface_tag_bottom, substrate
|
||||
|
||||
|
||||
def traces_to_gmsh_mag(traces, mesh_out, bbox, model_name='gerbonara_board', log=True, copper_thickness=0.035, board_thickness=0.8, air_box_margin_h=30.0, air_box_margin_v=80.0):
|
||||
import gmsh
|
||||
occ = gmsh.model.occ
|
||||
eps = 1e-6
|
||||
|
||||
gmsh.initialize()
|
||||
gmsh.model.add('gerbonara_board')
|
||||
if log:
|
||||
gmsh.logger.start()
|
||||
|
||||
toplevel_tag, interface_tag_top, interface_tag_bottom, substrate = _gmsh_coil_inductance_geometry(traces, mesh_out, bbox, copper_thickness, board_thickness, air_box_margin_h)
|
||||
|
||||
(x1, y1), (x2, y2) = bbox
|
||||
x1, y1 = x1-air_box_margin_h, y1-air_box_margin_h
|
||||
x2, y2 = x2+air_box_margin_h, y2+air_box_margin_h
|
||||
w, d = x2-x1, y2-y1
|
||||
z0 = -2*copper_thickness-board_thickness-air_box_margin_v
|
||||
ab_h = 2*copper_thickness + board_thickness + 2*air_box_margin_v
|
||||
airbox = occ.addBox(x1, y1, z0, w, d, ab_h)
|
||||
|
||||
print('cut')
|
||||
with model_delta():
|
||||
|
|
@ -302,12 +275,10 @@ def traces_to_gmsh_mag(traces, mesh_out, bbox, model_name='gerbonara_board', log
|
|||
with model_delta():
|
||||
print(occ.fragment([(3, airbox)], [(3, toplevel_tag), (3, substrate)], removeObject=True, removeTool=False))
|
||||
|
||||
#occ.fragment([(3, substrate)], [(2, interface_tag_top), (2, interface_tag_bottom)])
|
||||
#occ.fragment([(3, airbox)], [(3, substrate), (3, toplevel_tag)])
|
||||
|
||||
print('Synchronizing')
|
||||
occ.synchronize()
|
||||
|
||||
first_geom = traces[0][0]
|
||||
pcx, pcy = first_geom.start.x, first_geom.start.y
|
||||
pcr = first_geom.width/2
|
||||
(_dim, plane_top), = gmsh.model.getEntitiesInBoundingBox(pcx-pcr-eps, pcy-pcr-eps, -eps, pcx+pcr+eps, pcy+pcr+eps, eps, 2)
|
||||
|
|
@ -341,7 +312,85 @@ def traces_to_gmsh_mag(traces, mesh_out, bbox, model_name='gerbonara_board', log
|
|||
gmsh.option.setNumber('Mesh.MeshSizeMin', 0.08)
|
||||
gmsh.option.setNumber('General.NumThreads', multiprocessing.cpu_count())
|
||||
|
||||
gmsh.write('/tmp/test.msh')
|
||||
print('Meshing')
|
||||
gmsh.model.mesh.generate(dim=3)
|
||||
print('Writing to', str(mesh_out))
|
||||
gmsh.write(str(mesh_out))
|
||||
|
||||
|
||||
def traces_to_gmsh_mag_mutual(traces, mesh_out, bbox, model_name='gerbonara_board', log=True, copper_thickness=0.035, board_thickness=0.8, air_box_margin_h=30.0, air_box_margin_v=80.0, mutual_offset=(0, 0, 5), mutual_rotation=(0, 0, 0)):
|
||||
import gmsh
|
||||
occ = gmsh.model.occ
|
||||
eps = 1e-6
|
||||
|
||||
gmsh.initialize()
|
||||
gmsh.model.add('gerbonara_board')
|
||||
if log:
|
||||
gmsh.logger.start()
|
||||
|
||||
m_dx, m_dy, m_dz = mutual_offset
|
||||
m_dz += 2*copper_thickness + board_thickness
|
||||
|
||||
toplevel_tag1, interface_tag_top1, interface_tag_bottom1, substrate1 = _gmsh_coil_inductance_geometry(traces, mesh_out, bbox, copper_thickness, board_thickness, air_box_margin_h)
|
||||
|
||||
occ.translate([(3, toplevel_tag1), (2, interface_tag_top1), (2, interface_tag_bottom1), (3, substrate1)], m_dx, m_dy, m_dz)
|
||||
|
||||
toplevel_tag2, interface_tag_top2, interface_tag_bottom2, substrate2 = _gmsh_coil_inductance_geometry(traces, mesh_out, bbox, copper_thickness, board_thickness, air_box_margin_h)
|
||||
|
||||
(x1, y1), (x2, y2) = bbox
|
||||
x1, y1 = x1-air_box_margin_h, y1-air_box_margin_h
|
||||
x2, y2 = x2+air_box_margin_h, y2+air_box_margin_h
|
||||
w, d = x2-x1, y2-y1
|
||||
z0 = -2*copper_thickness-board_thickness-air_box_margin_v
|
||||
ab_h = 4*copper_thickness + 2*board_thickness + 2*air_box_margin_v + m_dz
|
||||
airbox = occ.addBox(x1, y1, z0, w, d, ab_h)
|
||||
|
||||
print('cut')
|
||||
with model_delta():
|
||||
print(occ.cut([(3, airbox)], [(3, toplevel_tag1), (3, toplevel_tag2), (3, substrate1), (3, substrate2)], removeObject=True, removeTool=False))
|
||||
|
||||
print(f'Fragmenting airbox ({airbox}) with {toplevel_tag1=} {substrate1=} {toplevel_tag2=} {substrate2=}')
|
||||
with model_delta():
|
||||
print(occ.fragment([(3, airbox)], [(3, toplevel_tag1), (3, toplevel_tag2), (3, substrate1), (3, substrate2)], removeObject=True, removeTool=False))
|
||||
|
||||
print('Synchronizing')
|
||||
occ.synchronize()
|
||||
|
||||
first_geom = traces[0][0]
|
||||
pcx, pcy = first_geom.start.x, first_geom.start.y
|
||||
pcr = first_geom.width/2
|
||||
(_dim, plane_top1), = gmsh.model.getEntitiesInBoundingBox(pcx-pcr-eps, pcy-pcr-eps, m_dz-eps, pcx+pcr+eps, pcy+pcr+eps, m_dz+eps, 2)
|
||||
(_dim, plane_bottom1), = gmsh.model.getEntitiesInBoundingBox(pcx-pcr-eps, pcy-pcr-eps, m_dz-board_thickness-eps, pcx+pcr+eps, pcy+pcr+eps, m_dz-board_thickness+eps, 2)
|
||||
(_dim, plane_top2), = gmsh.model.getEntitiesInBoundingBox(pcx-pcr-eps, pcy-pcr-eps, -eps, pcx+pcr+eps, pcy+pcr+eps, eps, 2)
|
||||
(_dim, plane_bottom2), = gmsh.model.getEntitiesInBoundingBox(pcx-pcr-eps, pcy-pcr-eps, -board_thickness-eps, pcx+pcr+eps, pcy+pcr+eps, -board_thickness+eps, 2)
|
||||
|
||||
substrate1_physical = gmsh.model.add_physical_group(3, [substrate1], name='substrate1')
|
||||
trace1_physical = gmsh.model.add_physical_group(3, [toplevel_tag1], name='trace1')
|
||||
substrate2_physical = gmsh.model.add_physical_group(3, [substrate2], name='substrate2')
|
||||
trace2_physical = gmsh.model.add_physical_group(3, [toplevel_tag2], name='trace2')
|
||||
airbox_physical = gmsh.model.add_physical_group(3, [airbox], name='airbox')
|
||||
|
||||
interface_top1_physical = gmsh.model.add_physical_group(2, [plane_top1], name='interface_top1')
|
||||
interface_bottom1_physical = gmsh.model.add_physical_group(2, [plane_bottom1], name='interface_bottom1')
|
||||
interface_top2_physical = gmsh.model.add_physical_group(2, [plane_top2], name='interface_top2')
|
||||
interface_bottom2_physical = gmsh.model.add_physical_group(2, [plane_bottom2], name='interface_bottom2')
|
||||
|
||||
airbox_adjacent = set(gmsh.model.getAdjacencies(3, airbox)[1])
|
||||
in_bbox = {tag for _dim, tag in gmsh.model.getEntitiesInBoundingBox(x1+eps, y1+eps, z0+eps, x2-eps, y2-eps, z0+ab_h-eps, dim=2)}
|
||||
airbox_physical_surface = gmsh.model.add_physical_group(2, list(airbox_adjacent - in_bbox), name='airbox_surface')
|
||||
|
||||
points_airbox_adjacent = {tag for _dim, tag in gmsh.model.getBoundary([(3, airbox)], recursive=True, oriented=False)}
|
||||
print(f'{points_airbox_adjacent=}')
|
||||
points_inside = {tag for _dim, tag in gmsh.model.getEntitiesInBoundingBox(x1+eps, y1+eps, z0+eps, x1+w-eps, y1+d-eps, z0+ab_h-eps, dim=0)}
|
||||
#gmsh.model.mesh.setSize([(0, tag) for tag in points_airbox_adjacent - points_inside], 300e-3)
|
||||
|
||||
gmsh.option.setNumber('Mesh.MeshSizeFromCurvature', 32)
|
||||
gmsh.option.setNumber('Mesh.Smoothing', 10)
|
||||
gmsh.option.setNumber('Mesh.Algorithm3D', 10)
|
||||
gmsh.option.setNumber('Mesh.MeshSizeMax', 10)
|
||||
gmsh.option.setNumber('Mesh.MeshSizeMin', 0.08)
|
||||
gmsh.option.setNumber('General.NumThreads', multiprocessing.cpu_count())
|
||||
|
||||
print('Meshing')
|
||||
gmsh.model.mesh.generate(dim=3)
|
||||
print('Writing to', str(mesh_out))
|
||||
|
|
@ -475,6 +524,10 @@ def print_valid_twists(ctx, param, value):
|
|||
@click.option('--arc-tolerance', type=float, default=0.02)
|
||||
@click.option('--mesh-out', type=click.Path(writable=True, dir_okay=False, path_type=Path))
|
||||
@click.option('--mag-mesh-out', type=click.Path(writable=True, dir_okay=False, path_type=Path))
|
||||
@click.option('--mag-mesh-mutual-out', type=click.Path(writable=True, dir_okay=False, path_type=Path))
|
||||
@click.option('--mutual-offset-x', type=float, default=0)
|
||||
@click.option('--mutual-offset-y', type=float, default=0)
|
||||
@click.option('--mutual-offset-z', type=float, default=5)
|
||||
@click.option('--magneticalc-out', type=click.Path(writable=True, dir_okay=False, path_type=Path))
|
||||
@click.option('--clipboard/--no-clipboard', help='Use clipboard integration (requires wl-clipboard)')
|
||||
@click.option('--counter-clockwise/--clockwise', help='Direction of generated spiral. Default: clockwise when wound from the inside.')
|
||||
|
|
@ -482,7 +535,7 @@ def print_valid_twists(ctx, param, value):
|
|||
def generate(outfile, turns, outer_diameter, inner_diameter, via_diameter, via_drill, via_offset, trace_width, clearance,
|
||||
footprint_name, layer_pair, twists, clipboard, counter_clockwise, keepout_zone, keepout_margin,
|
||||
arc_tolerance, pcb, mesh_out, magneticalc_out, circle_segments, mag_mesh_out, copper_thickness,
|
||||
board_thickness):
|
||||
board_thickness, mag_mesh_mutual_out, mutual_offset_x, mutual_offset_y, mutual_offset_z):
|
||||
if 'WAYLAND_DISPLAY' in os.environ:
|
||||
copy, paste, cliputil = ['wl-copy'], ['wl-paste'], 'xclip'
|
||||
else:
|
||||
|
|
@ -827,6 +880,10 @@ def generate(outfile, turns, outer_diameter, inner_diameter, via_diameter, via_d
|
|||
if mag_mesh_out:
|
||||
traces_to_gmsh_mag(traces, mag_mesh_out, ((-r, -r), (r, r)), copper_thickness=copper_thickness, board_thickness=board_thickness)
|
||||
|
||||
if mag_mesh_mutual_out:
|
||||
m_dx, m_dy, m_dz = mutual_offset_x, mutual_offset_y, mutual_offset_z
|
||||
traces_to_gmsh_mag_mutual(traces, mag_mesh_mutual_out, ((-r, -r), (r, r)), copper_thickness=copper_thickness, board_thickness=board_thickness, mutual_offset=(m_dx, m_dy, m_dz))
|
||||
|
||||
if magneticalc_out:
|
||||
traces_to_magneticalc(traces, magneticalc_out)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue