Пример #1
0
    def __init__(self, Par, mesh):
        self.par = Par
        self.mesh = mesh

        # Persistent storage: Primary variables that are solved for
        self._psi = None
        self._vp = None # TODO: this will be renamed to self._a eventually

        # Temp storage: Stored on cells, nodes, and edges. 
        # Used in observables and other classes and fairly general purpose
        self._tmp_node_var = None
        self._tmp_edge_var = None
        self._tmp_cell_var = None

        # Temp Storage: Allocated only for reductions
        self._tmp_psi_real = None
        self._tmp_A_real = None

        # copied from variables/parameters.py
        self.solveA = np.bool(not np.isposinf(cfg.gl_parameter))

        if cfg.order_parameter == 'random': 
            self.order_parameter = 1.0
            self.randomize_order_parameter(level = cfg.random_level, seed = cfg.random_seed)
        else:
            self.order_parameter = cfg.order_parameter   # set order parameter manually

        # vector potential is set up here instead of its setter because 
        # we don't plan on supporting setter for it
        shapes = [(cfg.Nxa, cfg.Nya), (cfg.Nxb, cfg.Nyb)]
        self._vp = GArray(shape = shapes, dtype = cfg.dtype)
Пример #2
0
    def fixed_vortices(self, fixed_vortices):

        self.fixed_vortices_x, self.fixed_vortices_y, self.fixed_vortices_vorticity = self._vortices_format(
            fixed_vortices)
        self._fixed_vortices_correct()

        if self.fixed_vortices_x.size > 0:
            if self._vpi is None:
                shapes = [(cfg.Nxa, cfg.Nya), (cfg.Nxb, cfg.Nyb)]
                self._vpi = GArray(shape=shapes, dtype=cfg.dtype)

            ai, bi = self._vpi.get_vec_h()
            ai.fill(0.0)
            bi.fill(0.0)

            xg, yg = self.mesh.xy_grid

            for k in range(self.fixed_vortices_x.size):
                vangle = np.arctan2(yg - self.fixed_vortices_y[k],
                                    xg - self.fixed_vortices_x[k])
                vangle -= vangle[0, 0]

                ai += self.fixed_vortices_vorticity[k] * cfg.idx * np.diff(
                    vangle, axis=0)
                bi += self.fixed_vortices_vorticity[k] * cfg.idy * np.diff(
                    vangle, axis=1)

            self._vpi.need_htod_sync()
            self._vpi.sync()
        else:
            if self._vpi is not None:
                self._vpi.free()
                self._vpi = None

        self.__update_phase_lock_ns()
Пример #3
0
    def _update_gvpei(self):
        """Sets self.gvpei = (self.ae, self.be) + (ai, bi).
        To be executed in self.external_vector_potential and self.fixed_vortices setters."""

        assert (self.ae is None) == (self.be is None)

        ai, bi = None, None
        if self.fixed_vortices is not None and self.fixed_vortices._vpi is not None:
            ai, bi = self.fixed_vortices._vpi.get_vec_h()
            assert (ai is None) == (bi is None)

        vpei = None
        if self.ae is not None:
            if ai is not None:
                vpei = (self.ae + ai, self.be + bi)
            else:
                vpei = (self.ae, self.be)
        else:
            vpei = (ai, bi)

        if self._vpei is not None and vpei is None:
            self._vpei.free()
            self._vpei = None
        else:
            #TODO: easier if GArray supports like for vector storage
            shapes = [vpei[0].shape, vpei[1].shape]
            self._vpei = GArray(shape=shapes, dtype=cfg.dtype)
            self._vpei.set_vec_h(vpei[0], vpei[1])
            self._vpei.sync()
Пример #4
0
    def __init__(self, par, mesh, _vars, params, observables):
        self.par = par
        self.mesh = mesh
        self.vars = _vars
        self.params = params
        self.fixed_vortices = self.params.fixed_vortices
        self.observables = observables

        self.solveA = self.params.solveA

        self.__order_parameter_phase_lock_krnl = self.par.get_function(
            'order_parameter_phase_lock')
        self.__iterate_order_parameter_jacobi_step_krnl = self.par.get_function(
            'iterate_order_parameter_jacobi_step')
        self.__iterate_vector_potential_jacobi_step_krnl = self.par.get_function(
            'iterate_vector_potential_jacobi_step')

        self.__xpy_r_krnl = self.par.get_function('xpy_r')
        self.__xmy_r_krnl = self.par.get_function('xmy_r')

        self._random_t = np.uint32(1)
        if cfg.random_seed is not None:
            self._random_t = np.uint32(cfg.random_seed)

        # Alloc the rhs arrays
        self.vars._tmp_node_var = GArray(like=self.vars._psi)

        shapes = [(cfg.Nxa, cfg.Nya), (cfg.Nxb, cfg.Nyb)]
        self.vars._tmp_edge_var = GArray(shape=shapes, dtype=cfg.dtype)

        A_size = self.vars.vector_potential_h().size

        self.__gab_next = gpuarray.zeros(A_size, dtype=cfg.dtype)
        self.__gpsi_next = gpuarray.empty_like(self.vars.order_parameter_h())
        self.__gr2_max = gpuarray.zeros(1, dtype=np.int32)

        # Adjust stopping criteria according to precision
        if cfg.dtype is np.float32:
            if cfg.stop_criterion_order_parameter < 1e-6:
                cfg.stop_criterion_order_parameter = 1e-6

            if cfg.stop_criterion_vector_potential < 1e-6:
                cfg.stop_criterion_vector_potential = 1e-6
        else:
            if cfg.stop_criterion_order_parameter < 1e-12:
                cfg.stop_criterion_order_parameter = 1e-12

            if cfg.stop_criterion_vector_potential < 1e-12:
                cfg.stop_criterion_vector_potential = 1e-12

        cfg.stop_criterion_order_parameter = cfg.dtype(
            cfg.stop_criterion_order_parameter)
        cfg.stop_criterion_vector_potential = cfg.dtype(
            cfg.stop_criterion_vector_potential)
Пример #5
0
    def order_parameter(self, order_parameter):
        if isinstance(order_parameter, (np.complexfloating, complex, np.floating, float, np.integer, int)):
            order_parameter = cfg.dtype_complex(order_parameter) * np.ones((cfg.Nx, cfg.Ny), cfg.dtype_complex)
        assert order_parameter.shape == (cfg.Nx, cfg.Ny)

        if self._psi is None:
            self._psi = GArray(like = order_parameter)
        else:
            self._psi.set_h(order_parameter)

        self.set_order_parameter_to_zero_outside_material()
        self._psi.sync()
Пример #6
0
    def linear_coefficient(self, linear_coefficient):
        if callable(linear_coefficient):
            xg, yg = mesh.xy_grid
            lc = linear_coefficient(xg, yg)
        else:
            lc = linear_coefficient

        if np.isscalar(lc):
            lc = lc * np.ones(1)
        else:
            assert lc.shape == (cfg.Nx, cfg.Ny)

        self._epsilon = GArray(like=lc.astype(cfg.dtype))
Пример #7
0
    def _alloc_free_temporary_gpu_storage(self, action):
        assert action in ['alloc', 'free']

        if action == 'alloc':
            if self._tmp_psi_real is None:
                self._tmp_psi_real = GArray(self.par.grid_size, on =
                        GArray.on_device, dtype = cfg.dtype)
            if self._tmp_A_real is None and self.solveA:
                self._tmp_A_real = GArray(self.par.grid_size_A, on =
                        GArray.on_device, dtype = cfg.dtype)
        else:
            if self._tmp_psi_real is not None:
                self._tmp_psi_real.free()
                self._tmp_psi_real = None
            if self._tmp_A_real is not None:
                self._tmp_A_real.free()
                self._tmp_A_real = None
Пример #8
0
    def __update_phase_lock_ns(self):
        if self._phase_lock_ns is not None:
            self._phase_lock_ns.free()
            self._phase_lock_ns = None

        if self._phase_lock_radius is not None:
            xg, yg = self.mesh.xy_grid
            lock_grid = np.full((cfg.Nx, cfg.Ny), False, dtype=np.bool)
            for k in range(self.fixed_vortices_x.size):
                lock_grid = np.logical_or(
                    lock_grid,
                    np.square(xg - self.fixed_vortices_x[k]) +
                    np.square(yg - self.fixed_vortices_y[k]) <= np.square(
                        self._phase_lock_radius))

            ns = np.where(lock_grid)[0].astype(np.int32)
            if ns.size > 0:
                self._phase_lock_ns = GArray(like=ns)
Пример #9
0
    def material_tiling(self, material_tiling):

        if callable(material_tiling):
            xg, yg = self.xy_c_grid
            mt = material_tiling(xg, yg)
        else:
            mt = material_tiling

        if mt is not None:
            assert mt.shape == (cfg.Nxc, cfg.Nyc)

            self._mt = GArray(like=mt.astype(np.bool))
            #self.set_order_parameter_to_zero_outside_material()
            #self._mt.sync()
        else:
            if self._mt is not None:
                self._mt.free()
                self._mt = None
Пример #10
0
class Params(object):
    """This class contains setters and getters for parameters"""
    def __init__(self, mesh, vars):
        self.mesh = mesh
        self.vars = vars
        self.fixed_vortices = FixedVortices(self.mesh, self.vars)

        self.solveA = False

        self.linear_coefficient = cfg.linear_coefficient  # epsilon
        self.gl_parameter = cfg.gl_parameter  # kappa
        self.normal_conductivity = cfg.normal_conductivity  # sigma

        # homogeneous external magnetic field
        self._H = cfg.dtype(0.0)
        self.homogeneous_external_field_reset = cfg.homogeneous_external_field

        # x- and y- components of external vector potential for non-homogeneous external magnetic field
        self.ae, self.be = None, None

        # external and irregular vector potential
        # it should be kept self._vpei = (self.ae, self.be) + (ai, bi)
        self._vpei = None

        # non-homogeneous external magnetic field
        self.external_field = cfg.external_field

        self.order_parameter_Langevin_coefficient = cfg.order_parameter_Langevin_coefficient

        self.vector_potential_Langevin_coefficient = cfg.vector_potential_Langevin_coefficient

    def __del__(self):
        pass

    @property
    def linear_coefficient(self):
        """ Sets/gets epsilon (linear coefficient)"""
        if self._epsilon.size == 1:
            return np.full((cfg.Nx, cfg.Ny),
                           self._epsilon.get_h(),
                           dtype=cfg.dtype)
        else:
            return self._epsilon.get_h()

    @linear_coefficient.setter
    def linear_coefficient(self, linear_coefficient):
        if callable(linear_coefficient):
            xg, yg = mesh.xy_grid
            lc = linear_coefficient(xg, yg)
        else:
            lc = linear_coefficient

        if np.isscalar(lc):
            lc = lc * np.ones(1)
        else:
            assert lc.shape == (cfg.Nx, cfg.Ny)

        self._epsilon = GArray(like=lc.astype(cfg.dtype))

    def linear_coefficient_h(self):
        if self._epsilon.size != 1:
            return self._epsilon.get_d_obj()

        return np.uintp(0)

    def linear_coefficient_scalar_h(self):
        if self._epsilon.size == 1:
            return self._epsilon.get_h()

        return cfg.dtype(0.0)

    @property
    def gl_parameter(self):
        """ Sets/gets GL parameter"""
        return self._kappa

    @gl_parameter.setter
    def gl_parameter(self, gl_parameter):
        if gl_parameter is None or np.isnan(gl_parameter) or np.isinf(
                gl_parameter):
            gl_parameter = np.inf
        assert isinstance(gl_parameter,
                          (np.floating, float, np.integer, int)) and (
                              np.isposinf(gl_parameter) or gl_parameter > 0.0)
        self._kappa = cfg.dtype(gl_parameter)

        self.solveA = np.bool(not np.isposinf(self._kappa))

    def gl_parameter_squared_h(self):
        if self.solveA:
            return cfg.dtype(self.gl_parameter**2)

        return cfg.dtype(-1.0)

    @property
    def normal_conductivity(self):
        """ Sets/gets normal conductivity"""
        return self._sigma

    @normal_conductivity.setter
    def normal_conductivity(self, normal_conductivity):
        assert isinstance(normal_conductivity,
                          (np.floating, float, np.integer,
                           int)) and normal_conductivity > 0.0
        self._sigma = cfg.dtype(normal_conductivity)
        self._rho = cfg.dtype(1.0 / normal_conductivity)

    @property
    def homogeneous_external_field(self):
        """
        Sets/gets homogeneous external field and 
        does not update vector potential.
        """
        return self._H

    @homogeneous_external_field.setter
    def homogeneous_external_field(self, homogeneous_external_field):
        self._H = cfg.dtype(homogeneous_external_field)

    def _update_vector_potential(self, homogeneous_external_field, reset):
        assert isinstance(homogeneous_external_field,
                          (np.floating, float, np.integer, int))
        if reset:
            self._H = cfg.dtype(homogeneous_external_field)

            # TODO: need a fill method in GArray
            # self.a.fill(0.0)
            # self.b.fill(0.0)

            a, b = self.vars._vp.get_vec_h()

            a.fill(0.0)
            b.fill(0.0)

            self.vars._vp.need_htod_sync()
            self.vars._vp.sync()

            delta_H = self._H
        else:
            delta_H = -self._H
            self._H = cfg.dtype(homogeneous_external_field)
            delta_H += self._H
            self.vars._vp.sync()

        # TODO: implement GPU version of ab initialization
        # Possible set of gauges, A = [g*y*H, (1-g)*x*H, 0] with any g, 0 <= g <= 1
        g = 0.5
        _, yg = self.mesh.xy_a_grid
        xg, _ = self.mesh.xy_b_grid

        a, b = self.vars._vp.get_vec_h()
        a -= g * (yg - 0.5 * cfg.Ly) * delta_H
        b += (1.0 - g) * (xg - 0.5 * cfg.Lx) * delta_H

        self.vars._vp.need_htod_sync()
        self.vars._vp.sync()

    def _homogeneous_external_field_delta(self, homogeneous_external_field):
        self._update_vector_potential(homogeneous_external_field, reset=False)

    homogeneous_external_field_delta = property(
        fset=_homogeneous_external_field_delta,
        doc="""Sets homogeneous external field, H, and adds to the vector 
              potential deltaA, satisfying curl(deltaA) = deltaH, where 
              deltaH = H - Hold and Hold is homogeneous external field 
              before update.""")

    def _homogeneous_external_field_reset(self, homogeneous_external_field):
        self._update_vector_potential(homogeneous_external_field, reset=True)

    homogeneous_external_field_reset = property(
        fset=_homogeneous_external_field_reset,
        doc="""Sets homogeneous external field, H, and sets vector 
              potential, A, satisfying curl(A) = H.""")

    def _update_gvpei(self):
        """Sets self.gvpei = (self.ae, self.be) + (ai, bi).
        To be executed in self.external_vector_potential and self.fixed_vortices setters."""

        assert (self.ae is None) == (self.be is None)

        ai, bi = None, None
        if self.fixed_vortices is not None and self.fixed_vortices._vpi is not None:
            ai, bi = self.fixed_vortices._vpi.get_vec_h()
            assert (ai is None) == (bi is None)

        vpei = None
        if self.ae is not None:
            if ai is not None:
                vpei = (self.ae + ai, self.be + bi)
            else:
                vpei = (self.ae, self.be)
        else:
            vpei = (ai, bi)

        if self._vpei is not None and vpei is None:
            self._vpei.free()
            self._vpei = None
        else:
            #TODO: easier if GArray supports like for vector storage
            shapes = [vpei[0].shape, vpei[1].shape]
            self._vpei = GArray(shape=shapes, dtype=cfg.dtype)
            self._vpei.set_vec_h(vpei[0], vpei[1])
            self._vpei.sync()

    @property
    def external_vector_potential(self):
        """Sets/gets external vector potential."""
        assert (self.ae is None) == (self.be is None)

        if self.ae is not None:
            return self.ae, self.be

        return None

    @external_vector_potential.setter
    def external_vector_potential(self, external_vector_potential):
        if external_vector_potential is not None:
            Ax, Ay = external_vector_potential
            assert (Ax is None) == (Ay is None)
        else:
            Ax = None

        if Ax is not None:
            assert Ax.shape == (cfg.Nxa, cfg.Nya)
            assert Ay.shape == (cfg.Nxb, cfg.Nyb)
            self.ae = Ax
            self.be = Ay
        else:
            self.ae, self.be = None, None

        self._update_gvpei()

    @property
    def external_irregular_vector_potential(self):
        """ Sets/gets external irregular vector potential"""
        if self._vpei is not None:
            return self._vpei.get_vec_h()

        return None

    def external_irregular_vector_potential_h(self):
        if self._vpei is not None:
            return self._vpei.get_d_obj()

        return np.uintp(0)

    @property
    def external_field(self):
        """
        Sets/gets external (non-homogeneous) magnetic field.
        Setter accepts only a number now.
        """
        # TODO: return curl(A) for non-homogeneous external_field
        A = self.external_vector_potential
        if A is not None:
            Ax, Ay = A
            # TODO: check expression below
            return (-np.diff(Ax, axis=1) * cfg.idy +
                    np.diff(Ay, axis=0) * cfg.idx)
        else:
            return None

    @external_field.setter
    def external_field(self, external_field):
        if external_field is not None:
            # NOTE: placeholder, accepts only a number now
            # TODO: solve equation curl(Aext) = Hext(r) for nonuniform field Hext(r)

            # Possible set of gauges, A = [g*y*H, (1-g)*x*H, 0] with any g, 0 <= g <= 1
            g = 0.5
            _, yg = self.mesh.xy_a_grid
            xg, _ = self.mesh.xy_b_grid

            Ax = -g * (yg - 0.5 * cfg.Ly) * external_field
            Ay = (1.0 - g) * (xg - 0.5 * cfg.Lx) * external_field

            self.external_vector_potential = (Ax, Ay)
        else:
            self.external_vector_potential = None

    @property
    def order_parameter_Langevin_coefficient(self):
        return self._psi_langevin_c

    @order_parameter_Langevin_coefficient.setter
    def order_parameter_Langevin_coefficient(
            self, order_parameter_Langevin_coefficient):
        assert isinstance(order_parameter_Langevin_coefficient,
                          (np.floating, float, np.integer, int))
        self._psi_langevin_c = cfg.dtype(order_parameter_Langevin_coefficient)

    @property
    def vector_potential_Langevin_coefficient(self):
        return self._ab_langevin_c

    @vector_potential_Langevin_coefficient.setter
    def vector_potential_Langevin_coefficient(
            self, vector_potential_Langevin_coefficient):
        assert isinstance(vector_potential_Langevin_coefficient,
                          (np.floating, float, np.integer, int))
        self._ab_langevin_c = cfg.dtype(vector_potential_Langevin_coefficient)
Пример #11
0
)

verbose = False

rs = [0.0001, 0.001, 0.01, 0.1, 0.3, 1.0]

test_e0_number, test_e0_passed = 0, 0
test_e1_number, test_e1_passed = 0, 0
test_c_number, test_c_passed = 0, 0

gl.solve._init_cg()

psi0 = gl.vars.order_parameter
ab0 = gl.vars.vector_potential

dpsi = GArray(like = psi0) 
dab  = GArray(shape = [ab0[0].shape, ab0[1].shape], dtype = gl.cfg.dtype)

for r in rs:
    
    # The following equalities are required:
    #   1) a_psi + b_psi*alpha_psi = 1
    #   2) a_A + b_A*alpha_A = 1, where b_A should be small
    a_b_alpha = [
        #a_psi, b_psi, alpha_psi,    a_A,       b_A,   alpha_A
        [1.0,   0.0,   0.0,          1.0-r,     r,     1.0    ], # must be first (j=0)
        [0.5,   0.5,   1.0,          1.0-r,     r,     1.0    ],
        [0.6976,0.72, 0.42,          1.0-r,     r,     1.0    ],
        [0.7923,0.31, 0.67,          1.0-r,     r,     1.0    ],
        [0.6976,0.72, 0.42,          1.0-0.7*r, 0.7*r, 1.0    ],
        [0.7923,0.31, 0.67,          1.0-0.6*r, 0.6*r, 1.0    ],
Пример #12
0
    def _tmp_cell_var_h(self):
        if self._tmp_cell_var is None:
            self._tmp_cell_var = GArray(shape = (cfg.Nxc, cfg.Nyc), 
                                          dtype = cfg.dtype)

        return self._tmp_cell_var.get_d_obj()
Пример #13
0
    def _tmp_edge_var_h(self):
        if self._tmp_edge_var is None:
            shapes = [(cfg.Nxa, cfg.Nya), (cfg.Nxb, cfg.Nyb)]
            self._tmp_edge_var = GArray(shape = shapes, dtype = cfg.dtype)

        return self._tmp_edge_var.get_d_obj()
Пример #14
0
    def _tmp_node_var_h(self):
        if self._tmp_node_var is None:
            self._tmp_node_var = GArray(like = self._psi)

        return self._tmp_node_var.get_d_obj() 
Пример #15
0
class Vars(object):
    """This class contains setters and getters for solution variables
    order parameter and vector potential"""

    def __init__(self, Par, mesh):
        self.par = Par
        self.mesh = mesh

        # Persistent storage: Primary variables that are solved for
        self._psi = None
        self._vp = None # TODO: this will be renamed to self._a eventually

        # Temp storage: Stored on cells, nodes, and edges. 
        # Used in observables and other classes and fairly general purpose
        self._tmp_node_var = None
        self._tmp_edge_var = None
        self._tmp_cell_var = None

        # Temp Storage: Allocated only for reductions
        self._tmp_psi_real = None
        self._tmp_A_real = None

        # copied from variables/parameters.py
        self.solveA = np.bool(not np.isposinf(cfg.gl_parameter))

        if cfg.order_parameter == 'random': 
            self.order_parameter = 1.0
            self.randomize_order_parameter(level = cfg.random_level, seed = cfg.random_seed)
        else:
            self.order_parameter = cfg.order_parameter   # set order parameter manually

        # vector potential is set up here instead of its setter because 
        # we don't plan on supporting setter for it
        shapes = [(cfg.Nxa, cfg.Nya), (cfg.Nxb, cfg.Nyb)]
        self._vp = GArray(shape = shapes, dtype = cfg.dtype)


    def __del__(self):
        pass


    @property
    def order_parameter(self):
        self._psi.sync()
        psi = self._psi.get_h().copy()
        return psi


    @order_parameter.setter
    def order_parameter(self, order_parameter):
        if isinstance(order_parameter, (np.complexfloating, complex, np.floating, float, np.integer, int)):
            order_parameter = cfg.dtype_complex(order_parameter) * np.ones((cfg.Nx, cfg.Ny), cfg.dtype_complex)
        assert order_parameter.shape == (cfg.Nx, cfg.Ny)

        if self._psi is None:
            self._psi = GArray(like = order_parameter)
        else:
            self._psi.set_h(order_parameter)

        self.set_order_parameter_to_zero_outside_material()
        self._psi.sync()


    def order_parameter_h(self):
        return self._psi.get_d_obj() 


    def set_order_parameter_to_zero_outside_material(self):

        if self._psi is None or not self.mesh.have_material_tiling():
            return

        mt_at_nodes = self.mesh._get_material_tiling_at_nodes()

        psi = self._psi.get_h()
        psi[~mt_at_nodes] = 0.0

        self._psi.need_htod_sync()
        self._psi.sync()


    def randomize_order_parameter(self, level=1.0, seed=None):
        """Randomizes order parameter:
            absolute value *= 1 - level*rand
            phase += level*pi*(2.0*rand()-1.0),
            where rand is uniformly distributed in [0, 1]
        """
        assert 0.0 <= level <= 1.0

        self._psi.sync()

        if seed is not None:
            np.random.seed(seed)

        data = (1.0 - level*np.random.rand(cfg.N)) * np.exp(level * 1.0j*np.pi*(2.0*np.random.rand(cfg.N) - 1.0))

        self._psi.set_h(data)
        self._psi.sync()


    @property
    def vector_potential(self):
        if self._vp is None:
            return (np.zeros((cfg.Nxa, cfg.Nya), dtype=cfg.dtype),
                    np.zeros((cfg.Nxb, cfg.Nyb), dtype=cfg.dtype))

        self._vp.sync()
        return self._vp.get_vec_h() 


    @vector_potential.setter
    def vector_potential(self, vector_potential):

        a, b = vector_potential
        self._vp.set_vec_h(a, b)
        self._vp.sync()


    def vector_potential_h(self):
        if self._vp is not None:
            return self._vp.get_d_obj()

        return np.uintp(0)

    #--------------------------
    # temporary arrays
    #--------------------------

    def _tmp_node_var_h(self):
        if self._tmp_node_var is None:
            self._tmp_node_var = GArray(like = self._psi)

        return self._tmp_node_var.get_d_obj() 


    def _tmp_edge_var_h(self):
        if self._tmp_edge_var is None:
            shapes = [(cfg.Nxa, cfg.Nya), (cfg.Nxb, cfg.Nyb)]
            self._tmp_edge_var = GArray(shape = shapes, dtype = cfg.dtype)

        return self._tmp_edge_var.get_d_obj()


    def _tmp_cell_var_h(self):
        if self._tmp_cell_var is None:
            self._tmp_cell_var = GArray(shape = (cfg.Nxc, cfg.Nyc), 
                                          dtype = cfg.dtype)

        return self._tmp_cell_var.get_d_obj()


    def _tmp_psi_real_h(self):
        if self._tmp_psi_real is not None:
            return self._tmp_psi_real.get_d_obj()

        return np.uintp(0)


    def _tmp_A_real_h(self):
        if self._tmp_A_real is not None:
            return self._tmp_A_real.get_d_obj()

        return np.uintp(0)

    def _alloc_free_temporary_gpu_storage(self, action):
        assert action in ['alloc', 'free']

        if action == 'alloc':
            if self._tmp_psi_real is None:
                self._tmp_psi_real = GArray(self.par.grid_size, on =
                        GArray.on_device, dtype = cfg.dtype)
            if self._tmp_A_real is None and self.solveA:
                self._tmp_A_real = GArray(self.par.grid_size_A, on =
                        GArray.on_device, dtype = cfg.dtype)
        else:
            if self._tmp_psi_real is not None:
                self._tmp_psi_real.free()
                self._tmp_psi_real = None
            if self._tmp_A_real is not None:
                self._tmp_A_real.free()
                self._tmp_A_real = None
Пример #16
0
class FixedVortices(object):
    """This class contains methods to fix and release vortices,
    specify irregular vector potential"""
    def __init__(self, mesh, vars):

        # irregular vector potential
        self._vpi = None

        self._phase_lock_ns = None

        self._phase_lock_radius = cfg.phase_lock_radius

        self.mesh = mesh
        self.vars = vars

        if cfg.fixed_vortices_correction is None:
            cfg.fixed_vortices_correction = 'none'

        assert cfg.fixed_vortices_correction in ('none', 'cell centers',
                                                 'vertices')

        self.fixed_vortices_correction = cfg.fixed_vortices_correction
        self.fixed_vortices = cfg.fixed_vortices

    def __del__(self):
        pass

    # |psi| around isolated vortex
    def __vortex_psi_abs(self, x, y):
        r2 = x**2 + y**2
        # (i) psi(0) = 0 and (ii) |psi(r)| = 1 - 1/(2*r^2) + O(1/r^4) for r to inf
        return (1.0 - np.exp(-r2)) / (1.0 + np.exp(-r2))

    def order_parameter_add_vortices(self, vortices, phase=True, deep=False):
        """Adds (global) phase winding to order parameter around fixed vortex positions"""
        vx, vy, vv = self._vortices_format(vortices)
        xg, yg = self.mesh.xy_grid
        psi = self.vars._psi.get_h()

        for k in range(vx.size):
            if phase:
                psi *= np.exp(1.0j * vv[k]  # add phase around vx[k], vy[k]
                              * np.arctan2(yg - vy[k], xg - vx[k]))
            if deep:
                psi *= np.power(  # add deep at vx[k], vy[k]
                    self.__vortex_psi_abs(xg - vx[k], yg - vy[k]),
                    np.abs(vv[k]))

        self.vars._psi.need_htod_sync()
        self.vars._psi.sync()

    def fixed_vortices_release(self):
        """Releases fixed vortices, i.e. creates natural vortices at 
        positions (fixed_vortices_x,fixed_vortices_y) by adding phase to order parameter"""

        self.vars._psi.sync()

        psi = self.vars._psi.get_h()
        psi *= np.exp(-1.0j * self.fixed_vortices_phase)

        self.vars._psi.need_htod_sync()
        self.vars._psi.sync()

        self.fixed_vortices = None
        self.phase_lock_radius = None

    def _vortices_format(self, vortices):
        if vortices is None:
            vortices = [[], []]
        assert isinstance(vortices, (list, tuple, dict))
        assert len(vortices) in [2, 3]
        if isinstance(vortices, (list, tuple)):
            vx, vy = vortices[0], vortices[1]
            vv = vortices[2] if len(vortices) == 3 else []
        elif isinstance(vortices, dict):
            vx, vy = vortices['x'], vortices['y']
            vv = vortices[2] if 'vorticity' in vortices else []
        if vx is None: vx = []
        if vy is None: vy = []
        if vv is None: vv = []
        vx, vy, vv = np.array(vx).flatten(), np.array(vy).flatten(), np.array(
            vv).flatten()
        vN = max(vx.size, vy.size, vv.size)
        if vx.size > 0 and vv.size == 0: vv = np.array([1])
        assert vx.size in [1, vN] and vy.size in [1, vN] and vv.size in [1, vN]

        fvx, fvy, fvv = [], [], []
        x, y, v = np.nan, np.nan, np.nan
        for i in range(vN):
            if i < vx.size: x = vx[i]
            if i < vy.size: y = vy[i]
            if i < vv.size: v = vv[i]
            if np.isnan(x) or np.isnan(y) or np.isnan(v):  # no nans
                continue
            fvx.append(x)
            fvy.append(y)
            fvv.append(v)

        return (np.array(fvx).astype(cfg.dtype),
                np.array(fvy).astype(cfg.dtype),
                np.array(fvv).astype(cfg.dtype))

    def _fixed_vortices_correct(self):
        # correction of vorticity; should be integer
        self.fixed_vortices_vorticity = np.round(self.fixed_vortices_vorticity)
        if self.fixed_vortices_correction == 'cell centers':
            # correction of vortex position; should be in centers of cells as magnetic field B[i,j]
            self.fixed_vortices_x = cfg.dx * (
                np.round(self.fixed_vortices_x / cfg.dx + 0.5) - 0.5)
            self.fixed_vortices_y = cfg.dy * (
                np.round(self.fixed_vortices_y / cfg.dy + 0.5) - 0.5)
        elif self.fixed_vortices_correction == 'vertices':
            # correction of vortex position; should be in grid vertices as order parameter psi[i,j]
            self.fixed_vortices_x = cfg.dx * np.round(
                self.fixed_vortices_x / cfg.dx)
            self.fixed_vortices_y = cfg.dy * np.round(
                self.fixed_vortices_y / cfg.dy)

    def _ab_phase(self, a, b):
        a = cfg.dx * np.r_[np.full(
            (1, cfg.Nya), 0.0, dtype=cfg.dtype),  # reuse a and b
                           a].cumsum(axis=0)
        b = cfg.dy * np.c_[np.full(
            (cfg.Nxb, 1), 0.0, dtype=cfg.dtype), b].cumsum(axis=1)
        return np.repeat(b[0:1, :], cfg.Nx,
                         axis=0) + a  # assume angle[0,0] = 0
        # return b + np.repeat(a[:,0:1], cfg.Ny, axis=1)                                 # equivalent expression

    @property
    def irregular_vector_potential(self):
        if self._vpi is None:
            return (np.zeros((cfg.Nxa, cfg.Nya), dtype=cfg.dtype),
                    np.zeros((cfg.Nxb, cfg.Nyb), dtype=cfg.dtype))

        self._vpi.sync()
        return self._vpi.get_vec_h()

    def irregular_vector_potential_h(self):
        if self._vpi is not None:
            return self._vpi.get_d_obj()

        return np.uintp(0)

    @property
    def fixed_vortices_phase(self):
        ai, bi = self.irregular_vector_potential
        return self._ab_phase(ai, bi)

    @property
    def fixed_vortices(self):
        return (self.fixed_vortices_x.copy(), self.fixed_vortices_y.copy(),
                self.fixed_vortices_vorticity.copy())

    @fixed_vortices.setter
    def fixed_vortices(self, fixed_vortices):

        self.fixed_vortices_x, self.fixed_vortices_y, self.fixed_vortices_vorticity = self._vortices_format(
            fixed_vortices)
        self._fixed_vortices_correct()

        if self.fixed_vortices_x.size > 0:
            if self._vpi is None:
                shapes = [(cfg.Nxa, cfg.Nya), (cfg.Nxb, cfg.Nyb)]
                self._vpi = GArray(shape=shapes, dtype=cfg.dtype)

            ai, bi = self._vpi.get_vec_h()
            ai.fill(0.0)
            bi.fill(0.0)

            xg, yg = self.mesh.xy_grid

            for k in range(self.fixed_vortices_x.size):
                vangle = np.arctan2(yg - self.fixed_vortices_y[k],
                                    xg - self.fixed_vortices_x[k])
                vangle -= vangle[0, 0]

                ai += self.fixed_vortices_vorticity[k] * cfg.idx * np.diff(
                    vangle, axis=0)
                bi += self.fixed_vortices_vorticity[k] * cfg.idy * np.diff(
                    vangle, axis=1)

            self._vpi.need_htod_sync()
            self._vpi.sync()
        else:
            if self._vpi is not None:
                self._vpi.free()
                self._vpi = None

        self.__update_phase_lock_ns()

    @property
    def phase_lock_radius(self):
        return self._phase_lock_radius

    def __set_phase_lock_radius(self, radius):
        assert radius is None or (isinstance(
            radius, (np.floating, float, np.integer, int)) and radius > 0.0)
        self._phase_lock_radius = radius

    #this was fixed_vortices.setter; I changed it to phase_lock_radius.
    @phase_lock_radius.setter
    def phase_lock_radius(self, radius):
        self.__set_phase_lock_radius(radius)
        self.__update_phase_lock_ns()

        # should update config too?
        #cfg.phase_lock_radius = self._phase_lock_radius

    def __update_phase_lock_ns(self):
        if self._phase_lock_ns is not None:
            self._phase_lock_ns.free()
            self._phase_lock_ns = None

        if self._phase_lock_radius is not None:
            xg, yg = self.mesh.xy_grid
            lock_grid = np.full((cfg.Nx, cfg.Ny), False, dtype=np.bool)
            for k in range(self.fixed_vortices_x.size):
                lock_grid = np.logical_or(
                    lock_grid,
                    np.square(xg - self.fixed_vortices_x[k]) +
                    np.square(yg - self.fixed_vortices_y[k]) <= np.square(
                        self._phase_lock_radius))

            ns = np.where(lock_grid)[0].astype(np.int32)
            if ns.size > 0:
                self._phase_lock_ns = GArray(like=ns)

    def _phase_lock_ns_h(self):
        if self._phase_lock_ns is not None:
            return self._phase_lock_ns.get_d_obj()

        return np.uintp(0)
Пример #17
0
class Grid(object):
    """This class contains methods to retrieve the grid information 
    at cell centroids, horizontal and vertical edge mid-points, 
    vertices/nodes as well as material tiling. 
    """
    def __init__(self):
        self._mt = None
        self.material_tiling = cfg.material_tiling

    def __del__(self):
        pass

    def have_material_tiling(self):
        if self._mt is None:
            return False

        return True

#--- grids ---#

    @property
    def xy(self):
        """Coordinates of grid vertices"""
        return (np.linspace(0.0,
                            cfg.Lx,
                            num=cfg.Nx,
                            endpoint=True,
                            dtype=cfg.dtype),
                np.linspace(0.0,
                            cfg.Ly,
                            num=cfg.Ny,
                            endpoint=True,
                            dtype=cfg.dtype))

    @property
    def xy_grid(self):
        """Coordinates of grid vertices, Nc-by-Ny grid"""
        x, y = self.xy
        return np.meshgrid(x, y, indexing='ij')

    @property
    def xy_a(self):
        """Coordinates of horizontal edge centers"""
        return (np.linspace(0.5 * cfg.dx,
                            cfg.Lx - 0.5 * cfg.dx,
                            num=cfg.Nxa,
                            endpoint=True,
                            dtype=cfg.dtype),
                np.linspace(0.0,
                            cfg.Ly,
                            num=cfg.Nya,
                            endpoint=True,
                            dtype=cfg.dtype))

    @property
    def xy_a_grid(self):
        """Coordinates of horizontal edge centers, Nxa-by-Nya grid"""
        x, y = self.xy_a
        return np.meshgrid(x, y, indexing='ij')

    @property
    def xy_b(self):
        """Coordinates of vertical edge centers"""
        return (np.linspace(0.0,
                            cfg.Lx,
                            num=cfg.Nxb,
                            endpoint=True,
                            dtype=cfg.dtype),
                np.linspace(0.5 * cfg.dy,
                            cfg.Ly - 0.5 * cfg.dy,
                            num=cfg.Nyb,
                            endpoint=True,
                            dtype=cfg.dtype))

    @property
    def xy_b_grid(self):
        """Coordinates of vertical edge centers, Nxb-by-Nyb grid"""
        x, y = self.xy_b
        return np.meshgrid(x, y, indexing='ij')

    @property
    def xy_c(self):
        """Coordinates of cell centers"""
        return (np.linspace(0.5 * cfg.dx,
                            cfg.Lx - 0.5 * cfg.dx,
                            num=cfg.Nxc,
                            endpoint=True,
                            dtype=cfg.dtype),
                np.linspace(0.5 * cfg.dy,
                            cfg.Ly - 0.5 * cfg.dy,
                            num=cfg.Nyc,
                            endpoint=True,
                            dtype=cfg.dtype))

    @property
    def xy_c_grid(self):
        """Coordinates of cell centers, Nxc-by-Nyc grid"""
        x, y = self.xy_c
        return np.meshgrid(x, y, indexing='ij')

    @property
    def material_tiling(self):
        """Material tiling: Returns True if material is superconducting in a cell, 
        else return False
        """
        if self._mt is not None:
            return self._mt.get_h().copy()
        else:
            return np.full((cfg.Nxc, cfg.Nyc), True, dtype=np.bool)

    @material_tiling.setter
    def material_tiling(self, material_tiling):

        if callable(material_tiling):
            xg, yg = self.xy_c_grid
            mt = material_tiling(xg, yg)
        else:
            mt = material_tiling

        if mt is not None:
            assert mt.shape == (cfg.Nxc, cfg.Nyc)

            self._mt = GArray(like=mt.astype(np.bool))
            #self.set_order_parameter_to_zero_outside_material()
            #self._mt.sync()
        else:
            if self._mt is not None:
                self._mt.free()
                self._mt = None

    def material_tiling_h(self):
        if self._mt is not None:
            return self._mt.get_d_obj()

        return np.uintp(0)

    def __in_material(self, x, y, prohibited_length=None):
        # TODO: test in_material() method
        if isinstance(x, (np.floating, float, np.integer, int)) and isinstance(
                y, (np.floating, float, np.integer, int)):
            xs, ys, scalar = np.array([x], dtype=self.dtype), np.array(
                [y], dtype=self.dtype), True
        else:
            xs, ys, scalar = x, y, False
        assert xs.shape == ys.shape
        if prohibited_length is None: prohibited_length = self.dtype(0.0)

        in_mt = np.full_like(xs, True, dtype=np.bool)

        in_mt[np.logical_or.reduce((
            xs < prohibited_length,
            xs > self.Lx - prohibited_length,
            ys < prohibited_length,
            ys > self.Ly - prohibited_length,
        ))] = False

        xg_c, yg_c = self.xy_c_grid
        xg_c, yg_c = self.flatten_c_array(xg_c), self.flatten_c_array(yg_c)

        in_mt = in_mt.reshape(-1)
        for e, (x_, y_) in enumerate(zip(xs.ravel(), ys.ravel())):
            if np.any(
                    np.logical_and(
                        np.square(xg_c - x_) + np.square(yg_c - y_) <
                        np.square(prohibited_length), ~self.mt)):
                im_mt[e] = False
        in_mt = in_mt.reshape(xs.shape)

        return in_mt if not scalar else in_mt[0]

    def _get_material_tiling_at_nodes(self):
        mt = self._mt.get_h()

        mt_c = np.full((1, cfg.Nyc), False, dtype=np.bool)
        mt_r = np.full((cfg.Nx, 1), False, dtype=np.bool)

        return (np.logical_or.reduce(
            (np.c_[mt_r, np.r_[mt_c, mt]], np.c_[mt_r, np.r_[mt, mt_c]],
             np.c_[np.r_[mt_c, mt], mt_r], np.c_[np.r_[mt, mt_c], mt_r])))

    def interpolate_ab_array_to_c_array(self, a, b):
        cx = 0.5 * (a[:, :-1] + a[:, 1:])
        cy = 0.5 * (b[:-1, :] + b[1:, :])
        return cx, cy

    def interpolate_ab_array_to_c_array_abs(self, a, b):
        cx, cy = self.interpolate_ab_array_to_c_array(a, b)
        return np.sqrt(np.square(cx) + np.square(cy))
Пример #18
0
    gl_parameter=np.inf,
    homogeneous_external_field=0.1,
)

verbose = False

a_b_alpha = [  # a + b*alpha = 1
    [1.0, 0.0, 0.0],
    [0.0, 1.0, 1.0],
    [0.5, 0.5, 1.0],
]
for i in range(10):
    alpha, b = np.random.rand(2)
    a_b_alpha.append([1.0 - b * alpha, b, alpha])

dpsi = GArray(like=gl.vars.order_parameter)

gl.solve._init_cg()

test_p_number, test_p_passed = 0, 0
for a, b, alpha in a_b_alpha:
    gl.vars.order_parameter = 1.0
    gl.vars.randomize_order_parameter(level=0.5)
    psi0 = gl.vars.order_parameter

    gl.params._homogeneous_external_field_reset = 0.01 + 0.1 * np.random.rand()

    apply_material_tiling(gl, verbose=False)

    E0 = gl.observables.free_energy
    if verbose: print('free_energy = %10.10g' % (E0))