emerge 1.0.6__py3-none-any.whl → 1.0.7__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.

Potentially problematic release.


This version of emerge might be problematic. Click here for more details.

@@ -19,7 +19,7 @@ from ...mesher import Mesher
19
19
  from ...material import Material
20
20
  from ...mesh3d import Mesh3D
21
21
  from ...coord import Line
22
- from ...geometry import GeoSurface
22
+ from ...geometry import GeoSurface, _GEOMANAGER
23
23
  from ...elements.femdata import FEMBasis
24
24
  from ...elements.nedelec2 import Nedelec2
25
25
  from ...solver import DEFAULT_ROUTINE, SolveRoutine
@@ -140,11 +140,13 @@ class Microwave3D:
140
140
  def reset_data(self):
141
141
  self.data = MWData()
142
142
 
143
- def reset(self):
144
- self.bc.reset()
143
+ def reset(self, _reset_bc: bool = True):
144
+ if _reset_bc:
145
+ self.bc.reset()
146
+ self.bc = MWBoundaryConditionSet(None)
145
147
  self.basis: FEMBasis = None
146
- self.bc = MWBoundaryConditionSet(None)
147
148
  self.solveroutine.reset()
149
+ self.assembler.cached_matrices = None
148
150
 
149
151
  def set_order(self, order: int) -> None:
150
152
  """Sets the order of the basis functions used. Currently only supports second order.
@@ -401,8 +403,10 @@ class Microwave3D:
401
403
  raise ValueError('The field basis is not yet defined.')
402
404
 
403
405
  logger.debug(' - Finding PEC TEM conductors')
404
- pecs: list[PEC] = self.bc.get_conductors() # type: ignore
405
406
  mesh = self.mesh
407
+
408
+ # Find all BC conductors
409
+ pecs: list[PEC] = self.bc.get_conductors() # type: ignore
406
410
 
407
411
  # Process all PEC Boundary Conditions
408
412
  pec_edges = []
@@ -418,19 +422,37 @@ class Microwave3D:
418
422
  edge_ids = list(mesh.tri_to_edge[:,itri].flatten())
419
423
  pec_edges.extend(edge_ids)
420
424
 
425
+ # All PEC edges
421
426
  pec_edges = list(set(pec_edges))
422
427
 
428
+ # Port mesh data
423
429
  tri_ids = mesh.get_triangles(port.tags)
424
430
  edge_ids = list(mesh.tri_to_edge[:,tri_ids].flatten())
425
431
 
426
- pec_port = np.array([i for i in pec_edges if i in set(edge_ids)])
432
+ port_pec_edges = np.array([i for i in pec_edges if i in set(edge_ids)])
427
433
 
428
- pec_islands = mesh.find_edge_groups(pec_port)
434
+ pec_islands = mesh.find_edge_groups(port_pec_edges)
429
435
 
436
+
430
437
  logger.debug(f' - Found {len(pec_islands)} PEC islands.')
431
438
 
432
439
  if len(pec_islands) != 2:
433
- raise ValueError(f' - Found {len(pec_islands)} PEC islands. Expected 2.')
440
+ pec_island_tags = {i: self.mesh._get_dimtags(edges=pec_edge_group) for i,pec_edge_group in enumerate(pec_islands)}
441
+ plus_term = None
442
+ min_term = None
443
+
444
+ for i, dimtags in pec_island_tags.items():
445
+ if not set(dimtags).isdisjoint(port.plus_terminal):
446
+ plus_term = i
447
+
448
+ if not set(dimtags).isdisjoint(port.minus_terminal):
449
+ min_term = i
450
+
451
+ if plus_term is None or min_term is None:
452
+ raise ValueError(f' - Found {len(pec_islands)} PEC islands without a terminal definition. Please use .set_terminals() to define which conductors are which polarity.')
453
+ logger.debug(f'Positive island = {pec_island_tags[plus_term]}')
454
+ logger.debug(f'Negative island = {pec_island_tags[min_term]}')
455
+ pec_islands = [pec_islands[plus_term], pec_islands[min_term]]
434
456
 
435
457
  groups = []
436
458
  for island in pec_islands:
@@ -603,6 +625,7 @@ class Microwave3D:
603
625
  elif TEM:
604
626
  G1, G2 = self._find_tem_conductors(port, sigtri=cond)
605
627
  cs, dls = self._compute_integration_line(G1,G2)
628
+ logger.debug(f'Integrating portmode from {cs[:,0]} to {cs[:,-1]}')
606
629
  mode.modetype = 'TEM'
607
630
  Ex, Ey, Ez = portfE(cs[0,:], cs[1,:], cs[2,:])
608
631
  voltage = np.sum(Ex*dls[0,:] + Ey*dls[1,:] + Ez*dls[2,:])
@@ -835,6 +858,100 @@ class Microwave3D:
835
858
  self._post_process(results, matset)
836
859
  return self.data
837
860
 
861
+ def _run_adaptive_mesh(self,
862
+ iteration: int,
863
+ frequency: float,
864
+ automatic_modal_analysis: bool = True) -> MWData:
865
+ """Executes a frequency domain study
866
+
867
+ The study is distributed over "n_workers" workers.
868
+ As optional parameter you may set a harddisc_threshold as integer. This determines the maximum
869
+ number of degrees of freedom before which the jobs will be cahced to the harddisk. The
870
+ path that will be used to cache the sparse matrices can be specified.
871
+ Additionally the term frequency_groups may be specified. This number will define in how
872
+ many groups the matrices will be pre-computed before they are send to workers. This can minimize
873
+ the total amound of RAM memory used. For example with 11 frequencies in gruops of 4, the following
874
+ frequency indices will be precomputed and then solved: [[1,2,3,4],[5,6,7,8],[9,10,11]]
875
+
876
+ Args:
877
+ iteration (int): The iteration number
878
+ frequency (float): The simulation frequency
879
+
880
+ Raises:
881
+ SimulationError: An error associated witha a problem during the simulation.
882
+
883
+ Returns:
884
+ MWSimData: The dataset.
885
+ """
886
+
887
+ self._simstart = time.time()
888
+ if self.bc._initialized is False:
889
+ raise SimulationError('Cannot run a modal analysis because no boundary conditions have been assigned.')
890
+
891
+ self._initialize_field()
892
+ self._initialize_bc_data()
893
+ self._check_physics()
894
+
895
+ if self.basis is None:
896
+ raise SimulationError('Cannot proceed, the simulation basis class is undefined.')
897
+
898
+ materials = self.mesh._get_material_assignment(self.mesher.volumes)
899
+
900
+ ### Does this move
901
+ logger.debug('Initializing single frequency settings.')
902
+
903
+ #### Port settings
904
+ all_ports = self.bc.oftype(PortBC)
905
+
906
+ ##### FOR PORT SWEEP SET ALL ACTIVE TO FALSE. THIS SHOULD BE FIXED LATER
907
+ ### COMPUTE WHICH TETS ARE CONNECTED TO PORT INDICES
908
+
909
+ for port in all_ports:
910
+ port.active=False
911
+
912
+
913
+ def run_job_single(job: SimJob):
914
+ for A, b, ids, reuse, aux in job.iter_Ab():
915
+ solution, report = self.solveroutine.solve(A, b, ids, reuse, id=job.id)
916
+ report.add(**aux)
917
+ job.submit_solution(solution, report)
918
+ return job
919
+
920
+
921
+ matset: list[tuple[np.ndarray, np.ndarray, np.ndarray]] = []
922
+
923
+ self._compute_modes(frequency)
924
+
925
+ logger.debug(f'Simulation frequency = {frequency/1e9:.3f} GHz')
926
+
927
+ if automatic_modal_analysis:
928
+ self._compute_modes(frequency)
929
+
930
+ job, mats = self.assembler.assemble_freq_matrix(self.basis, materials,
931
+ self.bc.boundary_conditions,
932
+ frequency,
933
+ cache_matrices=self.cache_matrices)
934
+
935
+ job.id = 0
936
+
937
+ logger.info('Starting solve')
938
+ job = run_job_single(job)
939
+
940
+
941
+ logger.info('Solving complete')
942
+
943
+ self.data.setreport(job.reports, freq=frequency, **self._params)
944
+
945
+ for variables, data in self.data.sim.iterate():
946
+ logger.trace(f'Sim variable: {variables}')
947
+ for item in data['report']:
948
+ item.logprint(logger.trace)
949
+
950
+ self.solveroutine.reset()
951
+ ### Compute S-parameters and return
952
+ self._post_process([job,], [mats,])
953
+ return self.data
954
+
838
955
  def eigenmode(self, search_frequency: float,
839
956
  nmodes: int = 6,
840
957
  k0_limit: float = 1,
@@ -868,10 +985,6 @@ class Microwave3D:
868
985
 
869
986
  materials = self.mesh._get_material_assignment(self.mesher.volumes)
870
987
 
871
- # er = self.mesh.retreive(lambda mat,x,y,z: mat.fer3d_mat(x,y,z), self.mesher.volumes)
872
- # ur = self.mesh.retreive(lambda mat,x,y,z: mat.fur3d_mat(x,y,z), self.mesher.volumes)
873
- # cond = self.mesh.retreive(lambda mat,x,y,z: mat.cond, self.mesher.volumes)[0,0,:]
874
-
875
988
  ### Does this move
876
989
  logger.debug('Initializing frequency domain sweep.')
877
990
 
@@ -73,7 +73,6 @@ class MWBoundaryConditionSet(BoundaryConditionSet):
73
73
  for bc in self.oftype(SurfaceImpedance):
74
74
  if bc.sigma > 10.0:
75
75
  bcs.append(bc)
76
-
77
76
  return bcs
78
77
 
79
78
  def get_type(self, bctype: Literal['PEC','ModalPort','LumpedPort','PMC','LumpedElement','RectangularWaveguide','Periodic','FloquetPort','SurfaceImpedance']) -> FaceSelection:
@@ -497,6 +496,8 @@ class ModalPort(PortBC):
497
496
  self._first_k0: float | None = None
498
497
  self._last_k0: float | None = None
499
498
 
499
+ self.plus_terminal: list[tuple[int, int]] = []
500
+ self.minus_terminal: list[tuple[int, int]] = []
500
501
 
501
502
  if cs is None:
502
503
  logger.info('Constructing coordinate system from normal port')
@@ -522,6 +523,26 @@ class ModalPort(PortBC):
522
523
  *axes (tuple, np.ndarray, Axis): The alignment vectors.
523
524
  """
524
525
  self.alignment_vectors = [_parse_axis(ax) for ax in axes]
526
+
527
+ def set_terminals(self, positive: Selection | GeoObject | None = None,
528
+ negative: Selection | GeoObject | None = None,
529
+ ground: Selection | GeoObject | None = None) -> None:
530
+ """Define which objects/faces/selection should be assigned the positive terminal
531
+ and which one the negative terminal.
532
+
533
+ The terminal assignment will be used to find an integration line for the impedance calculation.
534
+
535
+ Note: Ground is currently unused.
536
+
537
+ Args:
538
+ positive (Selection | GeoObject | None, optional): The postive terminal. Defaults to None.
539
+ negative (Selection | GeoObject | None, optional): The negative terminal. Defaults to None.
540
+ ground (Selection | GeoObject | None, optional): _description_. Defaults to None.
541
+ """
542
+ if positive is not None:
543
+ self.plus_terminal = positive.dimtags
544
+ if negative is not None:
545
+ self.minus_terminal = negative.dimtags
525
546
 
526
547
  @property
527
548
  def nmodes(self) -> int:
@@ -569,9 +590,10 @@ class ModalPort(PortBC):
569
590
  Returns:
570
591
  PortMode: The requested PortMode object
571
592
  """
593
+ options = self.modes[min(self.modes.keys(), key=lambda k: abs(k - k0))]
572
594
  if i is None:
573
- i = self.selected_mode
574
- return self.modes[min(self.modes.keys(), key=lambda k: abs(k - k0))][i]
595
+ i = min(len(options)-1, self.selected_mode)
596
+ return options[i]
575
597
 
576
598
  def global_field_function(self, k0: float = 0, which: Literal['E','H'] = 'E') -> Callable:
577
599
  ''' The field function used to compute the E-field.
@@ -18,7 +18,7 @@
18
18
  from __future__ import annotations
19
19
  from ...simulation_data import BaseDataset, DataContainer
20
20
  from ...elements.femdata import FEMBasis
21
- from dataclasses import dataclass
21
+ from dataclasses import dataclass, field
22
22
  import numpy as np
23
23
  from typing import Literal
24
24
  from loguru import logger
@@ -372,6 +372,7 @@ class EHField:
372
372
  freq: float
373
373
  er: np.ndarray
374
374
  ur: np.ndarray
375
+ aux: dict[str, np.ndarray] = field(default_factory=dict)
375
376
 
376
377
  @property
377
378
  def k0(self) -> float:
@@ -537,7 +538,7 @@ class EHField:
537
538
 
538
539
  return self.x, self.y, self.z, Fx, Fy, Fz
539
540
 
540
- def scalar(self, field: Literal['Ex','Ey','Ez','Hx','Hy','Hz','normE','normH'], metric: Literal['abs','real','imag','complex'] = 'real') -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
541
+ def scalar(self, field: Literal['Ex','Ey','Ez','Hx','Hy','Hz','normE','normH'] | str, metric: Literal['abs','real','imag','complex'] = 'real') -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
541
542
  """Returns the data X, Y, Z, Field based on the interpolation
542
543
 
543
544
  For animations, make sure to select the complex metric.
@@ -549,7 +550,11 @@ class EHField:
549
550
  Returns:
550
551
  (X,Y,Z,Field): The coordinates plus field scalar
551
552
  """
552
- field_arry = getattr(self, field)
553
+ if field in self.aux:
554
+ field_arry = self.aux[field]
555
+ else:
556
+ field_arry = getattr(self, field)
557
+
553
558
  if metric=='abs':
554
559
  field = np.abs(field_arry)
555
560
  elif metric=='real':
@@ -666,6 +671,10 @@ class MWField:
666
671
  self.excitation = {key: 0.0 for key in self._fields.keys()}
667
672
  self.excitation[self.port_modes[0].port_number] = 1.0 + 0j
668
673
 
674
+ def excite_port(self, number: int) -> None:
675
+ self.excitation = {key: 0.0 for key in self._fields.keys()}
676
+ self.excitation[self.port_modes[number].port_number] = 1.0 + 0j
677
+
669
678
  @property
670
679
  def EH(self) -> tuple[np.ndarray, np.ndarray]:
671
680
  ''' Return the electric and magnetic field as a tuple of numpy arrays '''
@@ -726,12 +735,20 @@ class MWField:
726
735
  self.Hx = Hx.reshape(shp)
727
736
  self.Hy = Hy.reshape(shp)
728
737
  self.Hz = Hz.reshape(shp)
729
-
738
+
730
739
  self._x = xs
731
740
  self._y = ys
732
741
  self._z = zs
733
- return EHField(xs, ys, zs, self.Ex, self.Ey, self.Ez, self.Hx, self.Hy, self.Hz, self.freq, self.er, self.ur)
734
-
742
+ field = EHField(xs, ys, zs, self.Ex, self.Ey, self.Ez, self.Hx, self.Hy, self.Hz, self.freq, self.er, self.ur)
743
+
744
+ return field
745
+
746
+ def _solution_quality(self) -> tuple[np.ndarray, np.ndarray]:
747
+ from .adaptive_mesh import compute_error_estimate
748
+
749
+ error_tet, max_elem_size = compute_error_estimate(self)
750
+ return error_tet, max_elem_size
751
+
735
752
  def boundary(self,
736
753
  selection: FaceSelection) -> EHField:
737
754
  nodes = self.mesh.nodes
@@ -539,7 +539,7 @@ class PVDisplay(BaseDisplay):
539
539
  XYZ=None,
540
540
  field: Literal['E','H'] = 'E',
541
541
  k0: float | None = None,
542
- mode_number: int = 0) -> None:
542
+ mode_number: int | None = None) -> None:
543
543
 
544
544
  if XYZ:
545
545
  X,Y,Z = XYZ
@@ -584,7 +584,10 @@ class PVDisplay(BaseDisplay):
584
584
  k0 = port.get_mode(0).k0
585
585
  else:
586
586
  k0 = 1
587
- port.selected_mode = mode_number
587
+
588
+ if isinstance(mode_number, int):
589
+ port.selected_mode = mode_number
590
+
588
591
  F = port.port_mode_3d_global(xf,yf,zf,k0, which=field)
589
592
 
590
593
  Fx = F[0,:].reshape(X.shape).T
@@ -547,7 +547,7 @@ class Simulation:
547
547
  self._set_mesh(dataset['mesh'])
548
548
  return self
549
549
 
550
- def generate_mesh(self) -> None:
550
+ def generate_mesh(self, regenerate: bool = False) -> None:
551
551
  """Generate the mesh.
552
552
  This can only be done after commit_geometry(...) is called and if frequencies are defined.
553
553
 
@@ -557,26 +557,27 @@ class Simulation:
557
557
  Raises:
558
558
  ValueError: ValueError if no frequencies are defined.
559
559
  """
560
- logger.trace('Starting mesh generation phase.')
561
- if not self._defined_geometries:
562
- self.commit_geometry()
563
-
564
- logger.trace(' (1) Installing periodic boundaries in mesher.')
565
- # Set the cell periodicity in GMSH
566
- if self._cell is not None:
567
- self.mesher.set_periodic_cell(self._cell)
568
-
569
- self.mw._initialize_bcs(_GEOMANAGER.get_surfaces())
560
+ if not regenerate:
561
+ logger.trace('Starting mesh generation phase.')
562
+ if not self._defined_geometries:
563
+ self.commit_geometry()
564
+
565
+ logger.trace(' (1) Installing periodic boundaries in mesher.')
566
+ # Set the cell periodicity in GMSH
567
+ if self._cell is not None:
568
+ self.mesher.set_periodic_cell(self._cell)
569
+
570
+ self.mw._initialize_bcs(_GEOMANAGER.get_surfaces())
570
571
 
571
- # Check if frequencies are defined: TODO: Replace with a more generic check
572
- if self.mw.frequencies is None:
573
- raise ValueError('No frequencies defined for the simulation. Please set frequencies before generating the mesh.')
572
+ # Check if frequencies are defined: TODO: Replace with a more generic check
573
+ if self.mw.frequencies is None:
574
+ raise ValueError('No frequencies defined for the simulation. Please set frequencies before generating the mesh.')
574
575
 
575
576
  gmsh.model.occ.synchronize()
576
577
 
577
578
  # Set the mesh size
578
579
  self.mesher._configure_mesh_size(self.mw.get_discretizer(), self.mw.resolution)
579
-
580
+
580
581
  logger.trace(' (2) Calling GMSH mesher')
581
582
  try:
582
583
  gmsh.logger.start()
@@ -589,6 +590,7 @@ class Simulation:
589
590
  logger.error('GMSH Mesh error detected.')
590
591
  print(_GMSH_ERROR_TEXT)
591
592
  raise
593
+
592
594
  logger.info('GMSH Meshing complete!')
593
595
  self.mesh._pre_update(self.mesher._get_periodic_bcs())
594
596
  self.mesh.exterior_face_tags = self.mesher.domain_boundary_face_tags
@@ -596,6 +598,14 @@ class Simulation:
596
598
  self._set_mesh(self.mesh)
597
599
  logger.trace(' (3) Mesh routine complete')
598
600
 
601
+ def _reset_mesh(self):
602
+ #gmsh.clear()
603
+ gmsh.model.mesh.clear()
604
+ mesh = Mesh3D(self.mesher)
605
+
606
+ self.mw.reset(False)
607
+ self._set_mesh(mesh)
608
+
599
609
  def parameter_sweep(self, clear_mesh: bool = True, **parameters: np.ndarray) -> Generator[tuple[float,...], None, None]:
600
610
  """Executes a parameteric sweep iteration.
601
611
 
@@ -654,6 +664,67 @@ class Simulation:
654
664
 
655
665
  self.mw.cache_matrices = True
656
666
 
667
+
668
+ def _beta_adaptive_mesh_refinement(self,
669
+ max_steps: int = 6,
670
+ convergence: float = 0.02,
671
+ refinement_percentage: float = 0.1,
672
+ refinement_ratio: float = 0.3,
673
+ growth_rate: float = 3) -> None:
674
+ """Beta implementation of Adaptive Mesh Refinement
675
+
676
+ Args:
677
+ max_steps (int, optional): _description_. Defaults to 6.
678
+ convergence (float, optional): _description_. Defaults to 0.02.
679
+ refinement_percentage (float, optional): _description_. Defaults to 0.1.
680
+ refinement_ratio (float, optional): _description_. Defaults to 0.3.
681
+ growth_rate (float, optional): _description_. Defaults to 3.
682
+ """
683
+ from .physics.microwave.adaptive_mesh import select_refinement_indices, reduce_point_set, compute_convergence
684
+
685
+ max_freq = np.max(self.mw.frequencies)
686
+
687
+ regenerate = False
688
+
689
+ Smats = []
690
+
691
+ for step in range(max_steps):
692
+ amr_params = dict(iter_step=step)
693
+ self.mw._params = amr_params
694
+ self.data.sim.new(**amr_params)
695
+
696
+
697
+ data = self.mw._run_adaptive_mesh(step, max_freq)
698
+
699
+ field = data.field[-1]
700
+
701
+ Smat_new = data.scalar[-1].Sp
702
+ Smats.append(Smat_new)
703
+ if step > 0:
704
+ S0 = Smats[-2]
705
+ S1 = Smats[-1]
706
+ conv = compute_convergence(S0, S1)
707
+ logger.info(f'Convergence = {conv}')
708
+ if conv < convergence:
709
+ logger.info('Mesh refinement passed!')
710
+ break
711
+ error, lengths = field._solution_quality()
712
+
713
+ idx = select_refinement_indices(error, refinement_percentage)
714
+
715
+ idx = idx[reduce_point_set(self.mw.mesh.centers[:,idx], growth_rate, lengths[idx], refinement_ratio)]
716
+ centers = self.mw.mesh.centers
717
+
718
+ self.mesher._reset_amr_points()
719
+ self._reset_mesh()
720
+ logger.debug(f'Adding {len(idx)} refinement points.')
721
+ for i in idx:
722
+ coord = centers[:,i]
723
+ size = lengths[i]
724
+ self.mesher.add_refinement_point(coord, refinement_ratio, size, growth_rate)
725
+
726
+ self.generate_mesh(True)
727
+ self.view(plot_mesh=True)
657
728
  def export(self, filename: str):
658
729
  """Exports the model or mesh depending on the extension.
659
730
 
emerge/_emerge/solver.py CHANGED
@@ -343,7 +343,7 @@ class Solver:
343
343
  return None
344
344
 
345
345
  def duplicate(self) -> Solver:
346
- return self.__class__()
346
+ return self.__class__(self.pre)
347
347
 
348
348
  def set_options(self, pivoting_threshold: float | None = None) -> None:
349
349
  """Write generic simulation options to the solver object.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emerge
3
- Version: 1.0.6
3
+ Version: 1.0.7
4
4
  Summary: An open source EM FEM simulator in Python
5
5
  Project-URL: Homepage, https://github.com/FennisRobert/EMerge
6
6
  Project-URL: Issues, https://github.com/FennisRobert/EMerge/issues
@@ -11,7 +11,8 @@ Requires-Dist: joblib>=1.5.1
11
11
  Requires-Dist: loguru>=0.7.3
12
12
  Requires-Dist: matplotlib>=3.8.0
13
13
  Requires-Dist: mkl!=2024.0; platform_machine == 'x86_64' or platform_machine == 'AMD64'
14
- Requires-Dist: numba>=0.57.0
14
+ Requires-Dist: numba<=0.60.0,>=0.57.0; platform_system == 'Linux'
15
+ Requires-Dist: numba>=0.57.0; platform_system != 'Linux'
15
16
  Requires-Dist: numpy<2.3,>=1.24
16
17
  Requires-Dist: pyvista>=0.45.2
17
18
  Requires-Dist: scipy>=1.14.0
@@ -1,4 +1,4 @@
1
- emerge/__init__.py,sha256=m1aBdjv_Ae2k7RzIgtl-5CMEH5FQmWw28SOk0V_ro0Y,3162
1
+ emerge/__init__.py,sha256=xexiF7GihNOUHqPZ2KViJFFaNNfRyc6l3Qz1PzWO_5w,3162
2
2
  emerge/__main__.py,sha256=WVf16sfrOI910QWohrQDaChZdRifMNoS6VKzCT6f3ZA,92
3
3
  emerge/cli.py,sha256=NU1uhwuZ6i50680v3_I4kDZPTHqz74gOYK71UBhb8oE,666
4
4
  emerge/ext.py,sha256=IBoHH5PQFj5pYMfp6r-uMpNNgbSe8c0g9x8qjBzzVmU,223
@@ -17,20 +17,20 @@ emerge/_emerge/geo2d.py,sha256=e_HkX1GQ2iYrdO0zeEgzVOzfGyU1WGJyjeGBAobOttE,3323
17
17
  emerge/_emerge/geometry.py,sha256=9WnZt2xtF4HEJfdPyT41i_q8gRMZRrG0C9PILaz1PvA,25523
18
18
  emerge/_emerge/howto.py,sha256=c4UxUNpA1tygr3OoR-LH-h0UZv-Tf9K8tpCiAU18BKE,8173
19
19
  emerge/_emerge/logsettings.py,sha256=OpsH_1dQAdZry_as8y0OQt4yKP_AMFfQG2d5Nz5yywg,4789
20
- emerge/_emerge/material.py,sha256=zXmKEZctqz4T574KSfRMdhiT2F_6l-QwiqlxNx6zkI0,17451
21
- emerge/_emerge/mesh3d.py,sha256=6NWTqJVwyaOhFKQgNghkH3zgrYFWbI0qAEBpvq-JOwI,35790
22
- emerge/_emerge/mesher.py,sha256=AUrMhXHHf1O5QtEyKlB172kV0B17jq9nzjq4JADZTV4,16079
20
+ emerge/_emerge/material.py,sha256=furDHD4rwkYCOjnh0GLz-Utjl5Z_NxDv0zWrk23Pygc,17459
21
+ emerge/_emerge/mesh3d.py,sha256=zPKOo1whf6yBpJxfEt89p3LXO4k1j7LSSMAGCDSK318,36946
22
+ emerge/_emerge/mesher.py,sha256=Ozks6t0LbdWEfDuh_06Hmm9nZz8vQLJl2FsYA7wzMMo,16854
23
23
  emerge/_emerge/periodic.py,sha256=dUuWqjlDR8mHtQR3ecINP2FFjJJ0cKg0blOVZ0PCcAo,12087
24
24
  emerge/_emerge/plot.py,sha256=cf1I9mj7EIUJcq8vmANlUkqoV6QqVaJaP-zlC-T9E18,8041
25
25
  emerge/_emerge/selection.py,sha256=ltT8ubMFG3-sFrAh7K7iAgSoBt3r25B02ShzMlOGSXQ,21527
26
26
  emerge/_emerge/settings.py,sha256=wZFMzQSnMEEJptatu--67El1L0I_YEv9S8QjqI69bfs,265
27
- emerge/_emerge/simmodel.py,sha256=yw21pUhO2_BB3vTN4UY7fhZxXuWNvcTaA5xRCcUg7vs,26525
27
+ emerge/_emerge/simmodel.py,sha256=Iu971xxJ5ggeB-KkrtxmGyV_-zHQN76z8_w1nSwpWJY,29371
28
28
  emerge/_emerge/simulation_data.py,sha256=23o-xbm6Q6s9sYisyK9u1GTmuaXRl0WDGQwzPO7lkr0,15115
29
- emerge/_emerge/solver.py,sha256=imgvQkVE9B3QEA1WmsBhhOLzHO44-Oh-onMXmLnfCFY,52980
29
+ emerge/_emerge/solver.py,sha256=3P-pcDWEpCEVnT2iFRRzC1hdYGUaz-xRzE68G3xvF1Q,52988
30
30
  emerge/_emerge/system.py,sha256=p4HNz7d_LMRNE9Gk75vVdFecDH2iN_groAM9u-yQTpk,1618
31
31
  emerge/_emerge/elements/__init__.py,sha256=I3n9aic6lJW-oGeqTEZ-Fpxvyl2i-WqsHdnrM3v1oB8,799
32
32
  emerge/_emerge/elements/femdata.py,sha256=ZSB7dICyU3GOWbxpuowBc-Khh2mpXa02ZfMkHwdDol4,8377
33
- emerge/_emerge/elements/index_interp.py,sha256=02CTHaokaAepBRvt7cHVwh3EpOA3sVE3qvEAkDjmwro,2072
33
+ emerge/_emerge/elements/index_interp.py,sha256=X7WcXKC9Qg7UABvLbAktda7InRkOhm7qOU-Wnefflp4,3381
34
34
  emerge/_emerge/elements/ned2_interp.py,sha256=BGRdJGXCcDdqMBf3pOvc_-m-vngRI1VvE5MUsqqf9Cw,27981
35
35
  emerge/_emerge/elements/nedelec2.py,sha256=OssFCnPp7wkMBcUISGvTgT94jayfGOmX0x-RctIYSuI,6645
36
36
  emerge/_emerge/elements/nedleg2.py,sha256=1SA6AvnbChhU2iodS1PVMUdbSn9wF2XKam12WTBDtsw,9049
@@ -54,16 +54,17 @@ emerge/_emerge/mth/pairing.py,sha256=i8bBvTeMmzgF0JdiDNJiTXxx913x4f10777pzD6FJo0
54
54
  emerge/_emerge/physics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  emerge/_emerge/physics/microwave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
56
  emerge/_emerge/physics/microwave/adaptive_freq.py,sha256=aWhijhCVAbnuwkru-I1AaRdY20uyozf6OWRIh9r2ijg,9786
57
- emerge/_emerge/physics/microwave/microwave_3d.py,sha256=mnfD6QPNVqtMMayu73yRdvErqL2-mPSqiKbOte9a3GQ,44632
58
- emerge/_emerge/physics/microwave/microwave_bc.py,sha256=bMV3SrIE5BNTdBbTncwy0N67TERsYWzzFypzFgDBW54,43697
59
- emerge/_emerge/physics/microwave/microwave_data.py,sha256=yAjWGzpTa14JfYKJVMMwx3ETONK_mjYRz98iDKEdDk8,49893
57
+ emerge/_emerge/physics/microwave/adaptive_mesh.py,sha256=bcPPbWoTaMsLK1QCIL6an5WaIIeKddCPPs2u7vKfAEs,22089
58
+ emerge/_emerge/physics/microwave/microwave_3d.py,sha256=OxZ3uJI1hhyGuUPV6ofWXCQfCu23URkyK2UJnpa9CLI,49141
59
+ emerge/_emerge/physics/microwave/microwave_bc.py,sha256=70zrxTZG_i9n2vBQAU1FOtK2Ia_KMi3qQeC9MU5aDHo,44872
60
+ emerge/_emerge/physics/microwave/microwave_data.py,sha256=eSWBrFmdYnOmCchf31jORwCriq2Ix1piGoGYHsvcF38,50551
60
61
  emerge/_emerge/physics/microwave/periodic.py,sha256=wYSUgLFVtCLqSG3EDKoCDRU93iPUzBdXzVRdHTRmbpI,3000
61
62
  emerge/_emerge/physics/microwave/port_functions.py,sha256=d-W1D-7P05MfXdOs7WlhPi_RqlSpC0HkYU6yl3GrxgE,2173
62
63
  emerge/_emerge/physics/microwave/sc.py,sha256=WZvoPhmHkfEv619RhmN09sXDBV0ryTqybwErA8Rc7lU,4735
63
64
  emerge/_emerge/physics/microwave/simjob.py,sha256=aCWCs7IXBfVBWWYhwyHvXSRHY3FOd3CK5ABcaFEsNnM,4927
64
65
  emerge/_emerge/physics/microwave/sparam.py,sha256=1SXGyr1UsrPnCIi4ffwobM4pzgkj50y4LrWCr_J5IRY,4946
65
66
  emerge/_emerge/physics/microwave/touchstone.py,sha256=pMcCOLWVqIKctcShcJxyaV-0rhRWXMSS1Jz14dVQEyY,5799
66
- emerge/_emerge/physics/microwave/assembly/assembler.py,sha256=sNsAa2bTSe9-tYMRePTOE2EKrqZhsJChD_anr4GC4Vo,23936
67
+ emerge/_emerge/physics/microwave/assembly/assembler.py,sha256=ZRaf_5zSZ2U0D5DmuYKCiyyxjonJLQV5pYsUm6aChj0,23982
67
68
  emerge/_emerge/physics/microwave/assembly/curlcurl.py,sha256=4CwMSUua8pvbp39gq2e3AxwVHOIVuPdr53qQM2BigQo,19688
68
69
  emerge/_emerge/physics/microwave/assembly/generalized_eigen.py,sha256=7jNU_hWd7q-ni53wmlhB5kmyJxp2xsx_WyBXZ6hPwo0,16907
69
70
  emerge/_emerge/physics/microwave/assembly/generalized_eigen_hb.py,sha256=tGf9EOzmp-dqtTodwYzcswuT_eLeZRtgdAZvgPz9QJo,17340
@@ -76,7 +77,7 @@ emerge/_emerge/plot/simple_plots.py,sha256=szIpmQmO8o6ubzB_E3zTJfEx16mJ3-OXrMYdD
76
77
  emerge/_emerge/plot/matplotlib/mpldisplay.py,sha256=e8V6EhGdCW7nRkSFvjHCcRO5uR-FcD0yHQ1nxPQCbp4,8674
77
78
  emerge/_emerge/plot/pyvista/__init__.py,sha256=CPclatEu6mFnJZzCQk09g6T6Fh20WTbiLAJGSwAnPXU,30
78
79
  emerge/_emerge/plot/pyvista/cmap_maker.py,sha256=_GVXYdtXpJwAO9O-Iekjzn6YcR0MVT8LNh12nqvF2IA,2498
79
- emerge/_emerge/plot/pyvista/display.py,sha256=k5hkIGZCyzYXw1zdDtWCDRwm2dwO0Xz8Sw9YTGGPo5k,45356
80
+ emerge/_emerge/plot/pyvista/display.py,sha256=nsiElERHYZPWX0uHwNoaocvfGtVTMsBdaO3hjTVDPvk,45429
80
81
  emerge/_emerge/plot/pyvista/display_settings.py,sha256=gV5hjRGEAl3oQeBPobas6b6JzYfMFrXIGtVSaeml4N0,1074
81
82
  emerge/_emerge/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
83
  emerge/_emerge/projects/_gen_base.txt,sha256=DqQz36PZg6v1ovQjHvPjd0t4AIbmikZdb9dmrNYsK3w,598
@@ -88,8 +89,8 @@ emerge/beta/dxf.py,sha256=Bw4lVk0TquOgCxTZV23BZN7PrgqxBrMZxbHV1waC5U0,50
88
89
  emerge/materials/__init__.py,sha256=Z9tu3m_nqj6F9I-FwoVoN0vCTYUlFesH3KxJ38wkZck,19
89
90
  emerge/materials/isola.py,sha256=kSDxHJZVn2CcanoUjlwRVKIPvadRbBybURTdIHWx728,18660
90
91
  emerge/materials/rogers.py,sha256=4u6ma_XQdXGKWE3WsFkaMTamCQNo9kTYSTU8S1gCAYU,3388
91
- emerge-1.0.6.dist-info/METADATA,sha256=wJysFFkQJJgPoC2pdAtzEvWLsMPB-usHAQweDuNwPqk,3306
92
- emerge-1.0.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- emerge-1.0.6.dist-info/entry_points.txt,sha256=8rFvAXticpKg4OTC8JEvAksnduW72KIEskCGG9XnFf8,43
94
- emerge-1.0.6.dist-info/licenses/LICENSE,sha256=VOCXWddrjMN5j7TvnSAOh1Dx7jkugdwq9Lqhycf5inc,17852
95
- emerge-1.0.6.dist-info/RECORD,,
92
+ emerge-1.0.7.dist-info/METADATA,sha256=tv3bFqll_HiWD6MDGr2K5tUC4Vy97vCO84EKQ2iGkQU,3400
93
+ emerge-1.0.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
94
+ emerge-1.0.7.dist-info/entry_points.txt,sha256=8rFvAXticpKg4OTC8JEvAksnduW72KIEskCGG9XnFf8,43
95
+ emerge-1.0.7.dist-info/licenses/LICENSE,sha256=VOCXWddrjMN5j7TvnSAOh1Dx7jkugdwq9Lqhycf5inc,17852
96
+ emerge-1.0.7.dist-info/RECORD,,
File without changes