def __init__(self, n_cpu=1, use_gpu=False, gpu_id=None, max_dpl_size=None, use_indicators=True, keep_raw_calculations=False, addacmd=[], suppress_C_output=True): # Check that adda is present and able to run try: with SuppressOutput(suppress_output=suppress_C_output): subprocess.check_call(['adda', '-V']) except (subprocess.CalledProcessError, OSError): raise DependencyMissing( 'adda', "adda is not included with HoloPy " "and must be installed separately. You should be able to run " "the command 'adda' from a terminal.") self.n_cpu = n_cpu self.use_gpu = use_gpu self.gpu_id = gpu_id self.max_dpl_size = max_dpl_size self.use_indicators = use_indicators self.keep_raw_calculations = keep_raw_calculations self.addacmd = addacmd self.suppress_C_output = suppress_C_output if use_gpu and n_cpu > 1: warnings.warn( "Adda cannot run on multiple CPUs, when running on GPU. 1 CPU will be used." ) super().__init__()
def _run_adda(self, scatterer, medium_wavevec, medium_index, temp_dir): medium_wavelen = 2 * np.pi / medium_wavevec if self.use_gpu: cmd = ['adda_ocl'] if self.gpu_id is not None: cmd.extend(['-gpu', str(self.gpu_id)]) elif self.n_cpu == 1: cmd = ['adda'] elif self.n_cpu > 1: cmd = ['mpiexec', '-n', str(self.n_cpu), 'adda_mpi'] cmd.extend(['-scat_matr', 'ampl']) cmd.extend(['-store_scat_grid']) cmd.extend(['-lambda', str(medium_wavelen)]) cmd.extend(['-save_geom']) cmd.extend(self.addacmd) predefined = isinstance(scatterer, tuple(_get_predefined_shape.keys())) layered = isinstance(scatterer, Sphere) and not np.isscalar(scatterer.r) if not predefined or self.use_indicators or layered: scat_args = self._adda_discretized(scatterer, medium_wavelen, medium_index, temp_dir) else: scat_args = self._adda_predefined(scatterer, medium_wavelen, medium_index, temp_dir) cmd.extend(scat_args) with SuppressOutput(suppress_output=self.suppress_C_output): subprocess.check_call(cmd, cwd=temp_dir)
def __init__(self, n_cpu = 1, max_dpl_size=None, use_indicators=True, keep_raw_calculations=False, addacmd=[], suppress_C_output=True): # Check that adda is present and able to run try: with SuppressOutput(): subprocess.check_call(['adda', '-V']) except (subprocess.CalledProcessError, OSError): raise DependencyMissing('adda', "adda is not included with HoloPy " "and must be installed separately. You should be able to run " "the command 'adda' from a terminal.") self.n_cpu = n_cpu self.max_dpl_size = max_dpl_size self.use_indicators = use_indicators self.keep_raw_calculations = keep_raw_calculations self.addacmd = addacmd self.suppress_C_output = suppress_C_output super().__init__()
def test_asm(): centers = np.array([[ 0., 0., 1.], [ 0., 0., -1.]]) m = np.array([ 1.5+0.1j, 1.5+0.1j]) size_p = np.array([ 1., 1.]) niter=200 eps = 1e-6 qeps1 = 1e-5 qeps2 = 1e-8 meth = 1 with SuppressOutput(): # The fortran code uses oppositely directed z axis (they have laser # propagation as positive, we have it negative), so we multiply the # z coordinate by -1 to correct for that. _, lmax, amn0, converged = scsmfo_min.amncalc( 1, centers[:,0], centers[:,1], -1.0 * centers[:,2], m.real, m.imag, size_p, niter, eps, qeps1, qeps2, meth, (0,0)) limit = lmax**2 + 2*lmax amn = amn0[:, 0:limit, :] asm_fwd = _asm_far(0, 0, amn, lmax) assert_allclose(asm_fwd, np.array([[ 2.73439859e-01 -6.75495808e-01j, -1.94648171e-18 -1.09606063e-18j], [ 1.94648171e-18 +1.09606063e-18j, 2.73439859e-01 -6.75495808e-01j]]))
def test_mie_multisphere_singlesph(): ''' Check that fields from mie_fields and tmatrix_fields are consistent at several points. This includes a check on the radial component of E_scat. ''' # sphere params x = 5. m = 1.2+0.1j pol = np.array([1., 0.]) # assume x polarization # points to check # at last two points: E_s kr = np.ones(4) * 6. thetas = np.array([0., pi/3., pi/2., pi/2.]) phis = np.array([0., pi/6., 0., pi/2.]) field_pts = np.vstack((kr, thetas, phis)) # calculate fields with Mie n_stop_mie = miescatlib.nstop(x) asbs = miescatlib.scatcoeffs(m, x, n_stop_mie) emie_x, emie_y, emie_z = mieangfuncs.mie_fields(field_pts, asbs, pol, 1, 1) # calculate fields with Multisphere with SuppressOutput(): _, lmax, amn0, conv = scsmfo_min.amncalc( 1, 0., 0., 0., m.real, m.imag, x, 100, 1e-6, 1e-8, 1e-8, 1, (0., 0.)) # increase qeps1 from usual here limit = lmax**2 + 2 * lmax amn = amn0[:, 0:limit, :] etm_x, etm_y, etm_z = mieangfuncs.tmatrix_fields(field_pts, amn, lmax, 0., pol, 1) assert_allclose(etm_x, emie_x, rtol = 1e-6, atol = 1e-6) assert_allclose(etm_y, emie_y, rtol = 1e-6, atol = 1e-6) assert_allclose(etm_z, emie_z, rtol = 1e-6, atol = 1e-6)
def _scsmfo_setup(self, scatterer, medium_wavevec, medium_index): """ Given multiple spheres, calculate amn coefficients for scattered field expansion in VSH using SCSMFO. Parameters ---------- scatterer : :mod:`.scatterer` object scatterer or list of scatterers to compute field for Returns ------- amn : arrays of field expansion coefficients """ if isinstance(scatterer,Sphere): scatterer=Spheres([scatterer]) elif not isinstance(scatterer, Spheres): raise TheoryNotCompatibleError(self, scatterer) # check for spheres being uniform for sph in scatterer.scatterers: if not np.isscalar(sph.n): raise TheoryNotCompatibleError(self, scatterer, "Multisphere" + " cannot compute scattering" + " from layered particles.") # check that the parameters are in a range where the multisphere # expansion will work for s in scatterer.scatterers: if s.r * medium_wavevec > 1e3: raise InvalidScatterer(s, "radius too large, field "+ "calculation would take forever") # switch to centroid weighted coordinate system tmatrix code expects # and nondimensionalize centers = (scatterer.centers - scatterer.centers.mean(0)) * medium_wavevec m = scatterer.n / medium_index if (centers > 1e4).any(): raise InvalidScatterer(scatterer, "Particle separation " "too large, calculation would take forever") with SuppressOutput(suppress_output=self.suppress_fortran_output): # The fortran code uses oppositely directed z axis (they # have laser propagation as positive, we have it negative), # so we multiply the z coordinate by -1 to correct for that. _, lmax, amn0, converged = scsmfo_min.amncalc( 1, centers[:,0], centers[:,1], -1.0 * centers[:,2], m.real, m.imag, scatterer.r * medium_wavevec, self.niter, self.eps, self.qeps1, self.qeps2, self.meth, (0,0)) # converged == 1 if the SCSMFO iterative solver converged # f2py converts F77 LOGICAL to int if not converged: raise MultisphereFailure() # chop off unused parts of amn0, the fortran code currently has a hard # coded number of parameters so it will return too many coefficients. # We truncate here to reduce the length of stuff we have to compute with # later. limit = lmax**2 + 2*lmax amn = amn0[:, 0:limit, :] if np.isnan(amn).any(): raise MultisphereFailure() return amn, lmax