Пример #1
0
    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__()
Пример #2
0
    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)
Пример #3
0
    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__()
Пример #4
0
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]]))
Пример #5
0
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)
Пример #6
0
    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