def deleteCoil(self): """Delete the coil Provided for debugging, should not be used. """ femm.mi_clearselected() femm.mi_selectgroup(2) femm.mi_deleteselected() femm.mi_deletematerial("Cuivre")
def deleteProjectile(self): """Delete the projectile Deletes the projectile (drawn) but doesn't erase its properties. """ femm.mi_clearselected() femm.mi_selectgroup(1) femm.mi_deleteselected() femm.mi_deletematerial("Projectile") if self.espace is not None: femm.mi_addsegment(0, -self.espace, 0, self.espace)
def computedLz(self, ite=0, rType="linear"): """Compute dLz Compute the variation of inductance while the projectile moves on the axis. If ite is zero, some guess is made about the number of iterations required for decent approximation. By default the projectile is moved linearly, but it is possible to set the movement type to tchebychev in order to minimize the Runge phenomenom. However not all the code is compatible with it. Rather than computing the variation of inductance, we compute the force on the projectile and correct it (explanations are available somewhere on this git :) ). Keyword Arguments: ite {number} -- number of steps (default: {0}) rType {str} -- type of movement, linear or tchebychev (default: {"linear"}) """ self.deleteProjectile() self.drawProjectile() (pas, pos, ite) = self._compute_range(ite, rType) force = numpy.zeros(ite) femm.mi_selectgroup(1) femm.mi_movetranslate2(0, pos[0], 4) for i in tqdm(range(ite // 2), disable=self.bHide): femm.mi_analyze() femm.mi_loadsolution() femm.mo_groupselectblock(1) force[i] = femm.mo_blockintegral(19) force[ite - i - 1] = -force[i] femm.mi_selectgroup(1) femm.mi_movetranslate2(0, pas[i], 4) self.dLz = 2 * force / self._i0**2 self.dLz_z = pos * 10**-3 self.dLz_nyquist = 1 / (2 * numpy.mean(pas) * 10**-3)
num_points = 25 # resolution of points inbetween z_start and z_end dz = (z_end - z_start) / (num_points - 1) z = np.linspace(z_start, z_end, num_points) fz = [] # START OF MOTION counter = 0 # Initialize a counter because I was too lazy to get the index in the for loop for z_loc in z: mag_y_loc = z_loc # Only start after the initial position has been used. if (counter > 0): femm.mi_movetranslate(0, dz) femm.mi_analyze(0) femm.mi_loadsolution() femm.mi_selectgroup(3) femm.mo_selectblock(0, mag_y_loc) fz.append(femm.mo_blockintegral(21) * 2) counter = counter + 1 # END OF MOTION # POST-PROCESSING femm.mi_saveas("final.fem") # Save the final simulation step max_loc = fz.index(max(fz)) # Find the location of maximum force plt.figure(1) plt.plot(z - z[max_loc], fz) plt.show() plt.xlabel('z (in)') plt.ylabel('F [N]')
def computeMuImpact(self, mus=[5, 10, 50, 100, 500, 1000, 5000], error=0.1): """Compute the impact of Mu The model is NOT LINEAR in mu. It is hard to guess what would be the effect of an increased suceptibility and it may highly modify the response of the coil. However, for some configuration the error is low (typically a long coil and a small projectile). This function provides some help to know if we can consider the model linear in Mu. Simply provide a range of possible susceptibilities for your projectile, and an acceptable relative error. We do not check the whole linearity, but simply in two points selected empirically. Therefore some care should be taken regarding the output of this helper method. Keyword Arguments: mus {list} -- [description] (default: {[5, 10, 50, 100, 500, 1000, 5000]}) error {number} -- [description] (default: {0.1}) """ _mu = self.mu res = [] test_res = [] print("Coil " + self._seed + " mus") for mu in mus: self.mu = mu self.deleteProjectile() self.drawProjectile() femm.mi_clearselected() femm.mi_selectgroup(1) femm.mi_analyze() femm.mi_loadsolution() femm.mo_groupselectblock(1) res.append(femm.mo_getcircuitproperties("Bobine")[2] / self._i0) femm.mi_movetranslate2(0, self.Lb / 4, 4) femm.mi_analyze() femm.mi_loadsolution() femm.mo_groupselectblock(1) test_res.append( femm.mo_getcircuitproperties("Bobine")[2] / self._i0) self.mu = _mu success = True errors = [] for i in range(0, len(test_res)): errors.append( numpy.abs((res[i] / res[0]) / (test_res[i] / test_res[0]) - 1)) if errors[-1] > error: success = False # break if success: return { 'valid': True, 'mus': mus, 'mu_Lz_0': res, 'mu_Lz_1': test_res, 'errors': errors } else: return { 'valid': False, 'mus': mus, 'mu_Lz_0': res, 'mu_Lz_1': test_res, 'errors': errors }
import femm import matplotlib.pyplot as plt femm.openfemm() femm.opendocument("coilgun.fem") femm.mi_saveas("temp.fem") femm.mi_seteditmode("group") z = [] f = [] for n in range(0, 16): femm.mi_analyze() femm.mi_loadsolution() femm.mo_groupselectblock(1) fz = femm.mo_blockintegral(19) z.append(n * 0.1) f.append(fz) femm.mi_selectgroup(1) femm.mi_movetranslate(0, -0.1) femm.closefemm() plt.plot(z, f) plt.ylabel('Force, N') plt.xlabel('Offset, in') plt.show()
def clearGroup(group): if group != 0: clearGroup(0) femm.mi_selectgroup(group) femm.mi_deleteselected() femm.mi_clearselected()
def rot(angle, group): femm.mi_selectgroup(group) femm.mi_moverotate(0, 0, angle) femm.mi_clearselected()
def mirrorZZ(n1, n2, group): femm.mi_selectgroup(group) femm.mi_mirror(n1.real, n1.imag, n2.real, n2.imag) femm.mi_clearselected()
def revolveOnce(angle, group): femm.mi_selectgroup(group) femm.mi_copyrotate(0, 0, angle, 1) femm.mi_clearselected()
def revolve(segments, group): femm.mi_selectgroup(group) phiStep = 360 / segments femm.mi_copyrotate(0, 0, phiStep, segments - 1) femm.mi_clearselected()