Ejemplo n.º 1
0
def test_sliced_iteration_llvm():
    size = (4, 4)
    src_arr = np.ones(size)
    dst_arr = np.zeros_like(src_arr)
    src_field = Field.create_from_numpy_array('src', src_arr)
    dst_field = Field.create_from_numpy_array('dst', dst_arr)

    a, b = sp.symbols("a b")
    update_rule = Assignment(dst_field[0, 0],
                             (a * src_field[0, 1] + a * src_field[0, -1] +
                              b * src_field[1, 0] + b * src_field[-1, 0]) / 4)

    x_end = TypedSymbol("x_end", "int")
    s = make_slice[1:x_end, 1]
    x_end_value = size[1] - 1
    import pystencils.llvm as llvm_generator
    ast = llvm_generator.create_kernel(sympy_cse_on_assignment_list(
        [update_rule]),
                                       iteration_slice=s)
    kernel = llvm_generator.make_python_function(ast)

    kernel(src=src_arr, dst=dst_arr, a=1.0, b=1.0, x_end=x_end_value)

    expected_result = np.zeros(size)
    expected_result[1:x_end_value, 1] = 1
    np.testing.assert_almost_equal(expected_result, dst_arr)
Ejemplo n.º 2
0
def test_variable_sized_fields():
    src_field = Field.create_generic('src', spatial_dimensions=2)
    dst_field = Field.create_generic('dst', spatial_dimensions=2)

    update_rule = Assignment(dst_field[0, 0],
                             (src_field[0, 1] + src_field[0, -1] +
                              src_field[1, 0] + src_field[-1, 0]) / 4)

    ast = create_cuda_kernel(sympy_cse_on_assignment_list([update_rule]))
    kernel = make_python_function(ast)

    size = (3, 3)
    src_arr = np.random.rand(*size)
    src_arr = add_ghost_layers(src_arr)
    dst_arr = np.zeros_like(src_arr)

    gpu_src_arr = gpuarray.to_gpu(src_arr)
    gpu_dst_arr = gpuarray.to_gpu(dst_arr)
    kernel(src=gpu_src_arr, dst=gpu_dst_arr)
    gpu_dst_arr.get(dst_arr)

    stencil = np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) / 4.0
    reference = convolve(remove_ghost_layers(src_arr),
                         stencil,
                         mode='constant',
                         cval=0.0)
    reference = add_ghost_layers(reference)
    np.testing.assert_almost_equal(reference, dst_arr)
Ejemplo n.º 3
0
    def __init__(self,
                 free_energy,
                 order_parameters,
                 domain_size,
                 data_handling=None,
                 name='pfn',
                 hydro_dynamic_relaxation_rate=1.0,
                 cahn_hilliard_relaxation_rates=1.0,
                 cahn_hilliard_gammas=1,
                 optimization=None):
        if optimization is None:
            optimization = {'openmp': False, 'target': Target.CPU}
        openmp = optimization.get('openmp', False)
        target = optimization.get('target', Target.CPU)

        if not hasattr(cahn_hilliard_relaxation_rates, '__len__'):
            cahn_hilliard_relaxation_rates = [cahn_hilliard_relaxation_rates
                                              ] * len(order_parameters)

        if not hasattr(cahn_hilliard_gammas, '__len__'):
            cahn_hilliard_gammas = [cahn_hilliard_gammas
                                    ] * len(order_parameters)

        if data_handling is None:
            data_handling = create_data_handling(domain_size,
                                                 periodicity=True,
                                                 parallel=False)
        dh = data_handling
        self.data_handling = dh

        stencil = LBStencil(Stencil.D3Q19) if dh.dim == 3 else LBStencil(
            Stencil.D2Q9)

        self.free_energy = free_energy

        # Data Handling
        kernel_parameters = {
            'cpu_openmp': openmp,
            'target': target,
            'ghost_layers': 2
        }
        gpu = target == Target.GPU
        phi_size = len(order_parameters)
        gl = kernel_parameters['ghost_layers']
        self.phi_field = dh.add_array(f'{name}_phi',
                                      values_per_cell=phi_size,
                                      gpu=gpu,
                                      latex_name='φ',
                                      ghost_layers=gl)
        self.mu_field = dh.add_array(f"{name}_mu",
                                     values_per_cell=phi_size,
                                     gpu=gpu,
                                     latex_name="μ",
                                     ghost_layers=gl)
        self.vel_field = dh.add_array(f"{name}_u",
                                      values_per_cell=data_handling.dim,
                                      gpu=gpu,
                                      latex_name="u",
                                      ghost_layers=gl)

        self.force_field = dh.add_array(f"{name}_force",
                                        values_per_cell=dh.dim,
                                        gpu=gpu,
                                        latex_name="F",
                                        ghost_layers=gl)

        self.phi = SlicedGetterDataHandling(self.data_handling,
                                            self.phi_field.name)
        self.mu = SlicedGetterDataHandling(self.data_handling,
                                           self.mu_field.name)
        self.velocity = SlicedGetterDataHandling(self.data_handling,
                                                 self.vel_field.name)
        self.force = SlicedGetterDataHandling(self.data_handling,
                                              self.force_field.name)

        self.ch_pdfs = []
        for i in range(len(order_parameters)):
            src = dh.add_array(f"{name}_ch_src{i}",
                               values_per_cell=stencil.Q,
                               ghost_layers=gl)
            dst = dh.add_array(f"{name}_ch_dst{i}",
                               values_per_cell=stencil.Q,
                               ghost_layers=gl)
            self.ch_pdfs.append((src, dst))
        self.hydro_pdfs = (dh.add_array(f"{name}_hydro_src",
                                        values_per_cell=stencil.Q,
                                        ghost_layers=gl),
                           dh.add_array(f"{name}_hydro_dst",
                                        values_per_cell=stencil.Q,
                                        ghost_layers=gl))

        # Compute Kernels
        mu_assignments = mu_kernel(self.free_energy, order_parameters,
                                   self.phi_field, self.mu_field)
        mu_assignments = [
            Assignment(a.lhs, a.rhs.doit()) for a in mu_assignments
        ]
        mu_assignments = sympy_cse_on_assignment_list(mu_assignments)
        self.mu_kernel = create_kernel(mu_assignments,
                                       **kernel_parameters).compile()

        force_rhs = force_from_phi_and_mu(self.phi_field.center_vector,
                                          dim=dh.dim,
                                          mu=self.mu_field.center_vector)
        force_rhs = [
            discretize_spatial(e,
                               dx=1,
                               stencil=fd_stencils_forth_order_isotropic)
            for e in force_rhs
        ]
        force_assignments = [
            Assignment(lhs, rhs)
            for lhs, rhs in zip(self.force_field.center_vector, force_rhs)
        ]
        self.force_kernel = create_kernel(force_assignments,
                                          **kernel_parameters).compile()

        self.ch_lb_kernels = []
        for i, (src, dst) in enumerate(self.ch_pdfs):
            ch_method = cahn_hilliard_lb_method(
                stencil,
                self.mu_field(i),
                relaxation_rate=cahn_hilliard_relaxation_rates[i],
                gamma=cahn_hilliard_gammas[i])
            opt = optimization.copy()
            opt['symbolic_field'] = src
            opt['symbolic_temporary_field'] = dst
            kernel = create_lb_function(
                lb_method=ch_method,
                optimization=opt,
                velocity_input=self.vel_field.center_vector,
                output={'density': self.phi_field(i)})
            self.ch_lb_kernels.append(kernel)

        opt = optimization.copy()
        opt['symbolic_field'] = self.hydro_pdfs[0]
        opt['symbolic_temporary_field'] = self.hydro_pdfs[1]
        self.hydro_lb_kernel = create_lb_function(
            stencil=stencil,
            relaxation_rate=hydro_dynamic_relaxation_rate,
            force=self.force_field.center_vector,
            output={'velocity': self.vel_field},
            optimization=opt)

        # Setter Kernels
        self.init_kernels = []
        for i in range(len(order_parameters)):
            ch_method = self.ch_lb_kernels[i].method
            init_assign = pdf_initialization_assignments(
                lb_method=ch_method,
                density=self.phi_field.center_vector[i],
                velocity=self.vel_field.center_vector,
                pdfs=self.ch_pdfs[i][0].center_vector)
            init_kernel = create_kernel(init_assign,
                                        **kernel_parameters).compile()
            self.init_kernels.append(init_kernel)

        init_assign = pdf_initialization_assignments(
            lb_method=self.hydro_lb_kernel.method,
            density=1,
            velocity=self.vel_field.center_vector,
            pdfs=self.hydro_pdfs[0].center_vector)
        self.init_kernels.append(
            create_kernel(init_assign, **kernel_parameters).compile())

        # Sync functions
        self.phi_sync = dh.synchronization_function([self.phi_field.name])
        self.mu_sync = dh.synchronization_function([self.mu_field.name])
        self.pdf_sync = dh.synchronization_function(
            [self.hydro_pdfs[0].name] + [src.name for src, _ in self.ch_pdfs])

        self.reset()
Ejemplo n.º 4
0
    def __init__(self,
                 free_energy,
                 order_parameters,
                 domain_size=None,
                 data_handling=None,
                 name='pf',
                 hydro_lbm_parameters=MappingProxyType({}),
                 hydro_dynamic_relaxation_rate=1.0,
                 cahn_hilliard_relaxation_rates=1.0,
                 cahn_hilliard_gammas=1,
                 density_order_parameter=None,
                 optimization=None,
                 kernel_params=MappingProxyType({}),
                 dx=1,
                 dt=1,
                 solve_cahn_hilliard_with_finite_differences=False,
                 order_parameter_force=None,
                 transformation_matrix=None,
                 concentration_to_order_parameters=None,
                 order_parameters_to_concentrations=None,
                 homogeneous_neumann_boundaries=False,
                 discretization='standard'):

        if optimization is None:
            optimization = {'openmp': False, 'target': Target.CPU}
        openmp = optimization.get('openmp', False)
        target = optimization.get('target', Target.CPU)

        if data_handling is None:
            data_handling = create_data_handling(domain_size,
                                                 periodicity=True,
                                                 parallel=False)

        self.free_energy = free_energy

        self.concentration_to_order_parameter = concentration_to_order_parameters
        self.order_parameters_to_concentrations = order_parameters_to_concentrations
        if transformation_matrix:
            op_transformation = np.array(transformation_matrix).astype(float)
            op_transformation_inv = np.array(
                transformation_matrix.inv()).astype(float)
            axes = ([-1], [1])
            if self.concentration_to_order_parameter is None:
                self.concentration_to_order_parameter = lambda c: np.tensordot(
                    c, op_transformation, axes=axes)
            if self.order_parameters_to_concentrations is None:
                self.order_parameters_to_concentrations = lambda p: np.tensordot(
                    p, op_transformation_inv, axes=axes)

        self.chemical_potentials = chemical_potentials_from_free_energy(
            free_energy, order_parameters)

        # ------------------ Adding arrays ---------------------
        gpu = target == Target.GPU
        self.gpu = gpu
        self.num_order_parameters = len(order_parameters)
        self.order_parameters = order_parameters
        pressure_tensor_size = len(
            symmetric_tensor_linearization(data_handling.dim))

        self.name = name
        self.phi_field_name = name + "_phi"
        self.mu_field_name = name + "_mu"
        self.vel_field_name = name + "_u"
        self.force_field_name = name + "_F"
        self.pressure_tensor_field_name = name + "_P"
        self.data_handling = data_handling

        dh = self.data_handling
        phi_size = len(order_parameters)
        self.phi_field = dh.add_array(self.phi_field_name,
                                      values_per_cell=phi_size,
                                      gpu=gpu,
                                      latex_name='φ')
        self.mu_field = dh.add_array(self.mu_field_name,
                                     values_per_cell=phi_size,
                                     gpu=gpu,
                                     latex_name="μ")
        self.vel_field = dh.add_array(self.vel_field_name,
                                      values_per_cell=data_handling.dim,
                                      gpu=gpu,
                                      latex_name="u")
        self.force_field = dh.add_array(self.force_field_name,
                                        values_per_cell=dh.dim,
                                        gpu=gpu,
                                        latex_name="F")
        self.pressure_tensor_field = data_handling.add_array(
            self.pressure_tensor_field_name,
            gpu=gpu,
            values_per_cell=pressure_tensor_size,
            latex_name='P')
        self.flag_interface = FlagInterface(data_handling, 'flags')

        # ------------------ Creating kernels ------------------
        phi = tuple(self.phi_field(i) for i in range(len(order_parameters)))
        F = self.free_energy.subs(
            {old: new
             for old, new in zip(order_parameters, phi)})

        if homogeneous_neumann_boundaries:

            def apply_neumann_boundaries(eqs):
                fields = [
                    data_handling.fields[self.phi_field_name],
                    data_handling.fields[self.pressure_tensor_field_name]
                ]
                flag_field = data_handling.fields[
                    self.flag_interface.flag_field_name]
                return add_neumann_boundary(eqs,
                                            fields,
                                            flag_field,
                                            "neumann_flag",
                                            inverse_flag=False)
        else:

            def apply_neumann_boundaries(eqs):
                return eqs

        # μ and pressure tensor update
        self.phi_sync = data_handling.synchronization_function(
            [self.phi_field_name], target=target)
        self.mu_eqs = mu_kernel(F, phi, self.phi_field, self.mu_field, dx)

        self.pressure_tensor_eqs = pressure_tensor_kernel(
            self.free_energy,
            order_parameters,
            self.phi_field,
            self.pressure_tensor_field,
            dx=dx,
            discretization=discretization)
        mu_and_pressure_tensor_eqs = self.mu_eqs + self.pressure_tensor_eqs
        mu_and_pressure_tensor_eqs = apply_neumann_boundaries(
            mu_and_pressure_tensor_eqs)
        self.mu_and_pressure_tensor_kernel = create_kernel(
            sympy_cse_on_assignment_list(mu_and_pressure_tensor_eqs),
            target=target,
            cpu_openmp=openmp).compile()

        # F Kernel
        extra_force = sp.Matrix([0] * self.data_handling.dim)
        if order_parameter_force is not None:
            for order_parameter_idx, force in order_parameter_force.items():
                extra_force += sp.Matrix([
                    f_i * self.phi_field(order_parameter_idx) for f_i in force
                ])
        self.force_eqs = force_kernel_using_pressure_tensor(
            self.force_field,
            self.pressure_tensor_field,
            dx=dx,
            extra_force=extra_force,
            discretization=discretization)
        self.force_from_pressure_tensor_kernel = create_kernel(
            apply_neumann_boundaries(self.force_eqs),
            target=target,
            cpu_openmp=openmp).compile()
        self.pressure_tensor_sync = data_handling.synchronization_function(
            [self.pressure_tensor_field_name], target=target)

        hydro_lbm_parameters = hydro_lbm_parameters.copy()
        # Hydrodynamic LBM
        if density_order_parameter is not None:
            density_idx = order_parameters.index(density_order_parameter)
            hydro_lbm_parameters['compute_density_in_every_step'] = True
            hydro_lbm_parameters['density_data_name'] = self.phi_field_name
            hydro_lbm_parameters['density_data_index'] = density_idx

        if 'optimization' not in hydro_lbm_parameters:
            hydro_lbm_parameters['optimization'] = optimization
        else:
            hydro_lbm_parameters['optimization'].update(optimization)

        self.hydro_lbm_step = LatticeBoltzmannStep(
            data_handling=data_handling,
            name=name + '_hydroLBM',
            relaxation_rate=hydro_dynamic_relaxation_rate,
            compute_velocity_in_every_step=True,
            force=tuple([self.force_field(i) for i in range(dh.dim)]),
            velocity_data_name=self.vel_field_name,
            kernel_params=kernel_params,
            flag_interface=self.flag_interface,
            time_step_order='collide_stream',
            **hydro_lbm_parameters)

        # Cahn-Hilliard LBMs
        if not hasattr(cahn_hilliard_relaxation_rates, '__len__'):
            cahn_hilliard_relaxation_rates = [cahn_hilliard_relaxation_rates
                                              ] * len(order_parameters)

        if not hasattr(cahn_hilliard_gammas, '__len__'):
            cahn_hilliard_gammas = [cahn_hilliard_gammas
                                    ] * len(order_parameters)

        self.cahn_hilliard_steps = []

        if solve_cahn_hilliard_with_finite_differences:
            if density_order_parameter is not None:
                raise NotImplementedError(
                    "density_order_parameter not supported when "
                    "CH is solved with finite differences")
            ch_step = CahnHilliardFDStep(
                self.data_handling,
                self.phi_field_name,
                self.mu_field_name,
                self.vel_field_name,
                target=target,
                dx=dx,
                dt=dt,
                mobilities=1,
                equation_modifier=apply_neumann_boundaries)
            self.cahn_hilliard_steps.append(ch_step)
        else:
            for i, op in enumerate(order_parameters):
                if op == density_order_parameter:
                    continue

                ch_method = cahn_hilliard_lb_method(
                    self.hydro_lbm_step.method.stencil,
                    self.mu_field(i),
                    relaxation_rate=cahn_hilliard_relaxation_rates[i],
                    gamma=cahn_hilliard_gammas[i])
                ch_step = LatticeBoltzmannStep(
                    data_handling=data_handling,
                    relaxation_rate=1,
                    lb_method=ch_method,
                    velocity_input_array_name=self.vel_field.name,
                    density_data_name=self.phi_field.name,
                    stencil='D3Q19' if self.data_handling.dim == 3 else 'D2Q9',
                    compute_density_in_every_step=True,
                    density_data_index=i,
                    flag_interface=self.hydro_lbm_step.boundary_handling.
                    flag_interface,
                    name=name + f"_chLbm_{i}",
                    optimization=optimization)
                self.cahn_hilliard_steps.append(ch_step)

        self._vtk_writer = None
        self.run_hydro_lbm = True
        self.density_order_parameter = density_order_parameter
        self.time_steps_run = 0
        self.reset()

        self.neumann_flag = 0