예제 #1
0
> size_t initialize(
	Init_Cond& init_cond,
	const double simulation_time,
	const std::vector<uint64_t>& cells,
	Grid& grid,
	std::mt19937_64& random_source,
	const double particle_temp_nrj_ratio,
	const unsigned long long int first_particle_id,
	const unsigned long long int particle_id_increase,
	const bool replace,
	const bool verbose
) {
	if (verbose && grid.get_rank() == 0) {
		std::cout << "Setting default particle state... ";
		std::cout.flush();
	}

	size_t nr_particles_created = 0;
	auto current_id_start = first_particle_id;
	for (const auto cell_id: cells) {
		random_source.seed(cell_id);

		const auto
			cell_start = grid.geometry.get_min(cell_id),
			cell_end = grid.geometry.get_max(cell_id),
			cell_length = grid.geometry.get_length(cell_id),
			cell_center = grid.geometry.get_center(cell_id);

		// classify cells for setting non-default initial state
		init_cond.add_cell(
			cell_id,
			cell_start,
			cell_end
		);

		auto* const cell_data = grid[cell_id];
		if (cell_data == NULL) {
			std::cerr <<  __FILE__ << "(" << __LINE__ << ") No data for cell: "
				<< cell_id
				<< std::endl;
			abort();
		}

		// set default state
		const auto
			number_density
				= init_cond.default_data.get_data(
					Number_Density_T(),
					cell_center,
					simulation_time
				),
			temperature
				= init_cond.default_data.get_data(
					Temperature_T(),
					cell_center,
					simulation_time
				),
			charge_mass_ratio
				= init_cond.default_data.get_data(
					Charge_Mass_Ratio_T(),
					cell_center,
					simulation_time
				),
			species_mass
				= init_cond.default_data.get_data(
					Particle_Species_Mass_T(),
					cell_center,
					simulation_time
				);
		const auto bulk_velocity
			= init_cond.default_data.get_data(
				Bulk_Velocity_T(),
				cell_center,
				simulation_time
			);
		const auto nr_particles
			= init_cond.default_data.get_data(
				Nr_Particles_In_Cell_T(),
				cell_center,
				simulation_time
			);

		auto new_particles
			= create_particles<
				Particle,
				Particle_Mass_T,
				Particle_Charge_Mass_Ratio_T,
				Particle_Position_T,
				Particle_Velocity_T,
				Particle_ID_T,
				Particle_Species_Mass_T
			>(
				bulk_velocity,
				Eigen::Vector3d{cell_start[0], cell_start[1], cell_start[2]},
				Eigen::Vector3d{cell_end[0], cell_end[1], cell_end[2]},
				Eigen::Vector3d{temperature, temperature, temperature},
				nr_particles,
				charge_mass_ratio,
				species_mass * number_density * cell_length[0] * cell_length[1] * cell_length[2],
				species_mass,
				particle_temp_nrj_ratio,
				random_source,
				current_id_start,
				particle_id_increase
			);
		nr_particles_created += nr_particles;

		if (replace) {
			(*cell_data)[Particles_T()] = std::move(new_particles);
		} else {
			(*cell_data)[Particles_T()].insert(
				(*cell_data)[Particles_T()].end(),
				new_particles.begin(),
				new_particles.end()
			);
		}

		current_id_start += nr_particles * particle_id_increase;
	}

	// set non-default initial conditions
	if (verbose && grid.get_rank() == 0) {
		std::cout << "done\nSetting non-default initial particle state... ";
		std::cout.flush();
	}
	for (size_t bdy_id = 0; bdy_id < init_cond.get_number_of_boundaries(); bdy_id++) {
		for (const auto& cell_id: init_cond.get_cells(bdy_id)) {
			const auto
				cell_start = grid.geometry.get_min(cell_id),
				cell_end = grid.geometry.get_max(cell_id),
				cell_length = grid.geometry.get_length(cell_id),
				cell_center = grid.geometry.get_center(cell_id);

			const auto
				number_density
					= init_cond.get_data(
						Number_Density_T(),
						bdy_id,
						cell_center,
						simulation_time
					),
				temperature
					= init_cond.get_data(
						Temperature_T(),
						bdy_id,
						cell_center,
						simulation_time
					),
				charge_mass_ratio
					= init_cond.get_data(
						Charge_Mass_Ratio_T(),
						bdy_id,
						cell_center,
						simulation_time
					),
				species_mass
					= init_cond.get_data(
						Particle_Species_Mass_T(),
						bdy_id,
						cell_center,
						simulation_time
					);
			const auto bulk_velocity
				= init_cond.get_data(
					Bulk_Velocity_T(),
					bdy_id,
					cell_center,
					simulation_time
				);
			const auto nr_particles
				= init_cond.get_data(
					Nr_Particles_In_Cell_T(),
					bdy_id,
					cell_center,
					simulation_time
				);

			auto* const cell_data = grid[cell_id];
			if (cell_data == NULL) {
				std::cerr <<  __FILE__ << "(" << __LINE__ << ") No data for cell: "
					<< cell_id
					<< std::endl;
				abort();
			}

			auto new_particles
				= create_particles<
					Particle,
					Particle_Mass_T,
					Particle_Charge_Mass_Ratio_T,
					Particle_Position_T,
					Particle_Velocity_T,
					Particle_ID_T,
					Particle_Species_Mass_T
				>(
					bulk_velocity,
					Eigen::Vector3d{cell_start[0], cell_start[1], cell_start[2]},
					Eigen::Vector3d{cell_end[0], cell_end[1], cell_end[2]},
					Eigen::Vector3d{temperature, temperature, temperature},
					nr_particles,
					charge_mass_ratio,
					species_mass * number_density * cell_length[0] * cell_length[1] * cell_length[2],
					species_mass,
					particle_temp_nrj_ratio,
					random_source,
					current_id_start,
					particle_id_increase
				);
			nr_particles_created += nr_particles;

			if (replace) {
				(*cell_data)[Particles_T()] = std::move(new_particles);
			} else {
				(*cell_data)[Particles_T()].insert(
					(*cell_data)[Particles_T()].end(),
					new_particles.begin(),
					new_particles.end()
				);
			}

			current_id_start += nr_particles * particle_id_increase;
		}
	}
	if (verbose && grid.get_rank() == 0) {
		std::cout << "done" << std::endl;
	}

	return nr_particles_created;
}
예제 #2
0
> void initialize_fluid(
	Init_Cond& init_cond,
	dccrg::Dccrg<Cell, Geometry>& grid,
	const std::vector<uint64_t>& cells,
	const double time,
	const double adiabatic_index,
	const double vacuum_permeability,
	const double proton_mass,
	const Mass_Density_Getter Mas,
	const Momentum_Density_Getter Mom,
	const Total_Energy_Density_Getter Nrj
) {
	// set default state
	for (const auto cell_id: cells) {
		const auto
			cell_start = grid.geometry.get_min(cell_id),
			cell_end = grid.geometry.get_max(cell_id),
			cell_center = grid.geometry.get_center(cell_id);

		init_cond.add_cell(
			cell_id,
			cell_start,
			cell_end
		);

		auto* const cell_data = grid[cell_id];
		if (cell_data == NULL) {
			std::cerr <<  __FILE__ << "(" << __LINE__ << ") No data for cell: "
				<< cell_id
				<< std::endl;
			abort();
		}

		const auto mass_density
			= proton_mass
			* [&](){
				try {
					return init_cond.default_data.get_data(mhd::Number_Density(), cell_center, time);
				} catch (mup::ParserError& e) {
					std::cout << "Couldn't get number density for default initial condition." << std::endl;
					throw;
				}
			}();
		const auto velocity
			= [&](){
				try {
					return init_cond.default_data.get_data(mhd::Velocity(), cell_center, time);
				} catch (mup::ParserError& e) {
					std::cout << "Couldn't get velocity for default initial condition." << std::endl;
					throw;
				}
			}();
		const auto pressure
			= [&](){
				try {
					return init_cond.default_data.get_data(mhd::Pressure(), cell_center, time);
				} catch (mup::ParserError& e) {
					std::cout << "Couldn't get pressure for default initial condition." << std::endl;
					throw;
				}
			}();

		Mas(*cell_data) = mass_density;
		Mom(*cell_data) = mass_density * velocity;
		if (mass_density > 0 and pressure > 0) {
			Nrj(*cell_data) = mhd::get_total_energy_density(
				mass_density,
				velocity,
				pressure,
				std::array<double, 3>{{0, 0, 0}},
				adiabatic_index,
				vacuum_permeability
			);
		} else {
			Nrj(*cell_data) = 0;
		}
	}

	// set non-default initial conditions
	for (size_t bdy_i = 0; bdy_i < init_cond.get_number_of_boundaries(); bdy_i++) {
		const auto& boundary_cells = init_cond.get_cells(bdy_i);

		for (const auto& cell_id: boundary_cells) {
			const auto cell_center = grid.geometry.get_center(cell_id);

			auto* const cell_data = grid[cell_id];
			if (cell_data == NULL) {
				std::cerr <<  __FILE__ << "(" << __LINE__ << ") No data for cell: "
					<< cell_id
					<< std::endl;
				abort();
			}

			const auto mass_density
				= proton_mass
				* [&](){
					try {
						return init_cond.get_data(mhd::Number_Density(), bdy_i, cell_center, time);
					} catch (mup::ParserError& e) {
						std::cout << "Couldn't get density for initial condition geometry " << bdy_i << std::endl;
						throw;
					}
				}();
			const auto velocity
				= [&](){
					try {
						return init_cond.get_data(mhd::Velocity(), bdy_i, cell_center, time);
					} catch (mup::ParserError& e) {
						std::cout << "Couldn't get velocity for initial condition geometry " << bdy_i << std::endl;
						throw;
					}
				}();
			const auto pressure
				= [&](){
					try {
						return init_cond.get_data(mhd::Pressure(), bdy_i, cell_center, time);
					} catch (mup::ParserError& e) {
						std::cout << "Couldn't get pressure for initial condition geometry " << bdy_i << std::endl;
						throw;
					}
				}();

			Mas(*cell_data) = mass_density;
			Mom(*cell_data) = mass_density * velocity;
			if (mass_density > 0 and pressure > 0) {
				Nrj(*cell_data) = mhd::get_total_energy_density(
					mass_density,
					velocity,
					pressure,
					std::array<double, 3>{{0, 0, 0}},
					adiabatic_index,
					vacuum_permeability
				);
			} else {
				Nrj(*cell_data) = 0;
			}
		}
	}
}
예제 #3
0
    > void initialize(
        const Geometries& geometries,
        Init_Cond& initial_conditions,
        const Background_Magnetic_Field& bg_B,
        dccrg::Dccrg<Cell, Geometry>& grid,
        const std::vector<uint64_t>& cells,
        const double time,
        const double adiabatic_index,
        const double vacuum_permeability,
        const double proton_mass,
        const bool verbose,
        const Mass_Density_Getter Mas,
        const Momentum_Density_Getter Mom,
        const Total_Energy_Density_Getter Nrj,
        const Magnetic_Field_Getter Mag,
        const Background_Magnetic_Field_Pos_X_Getter Bg_B_Pos_X,
        const Background_Magnetic_Field_Pos_Y_Getter Bg_B_Pos_Y,
        const Background_Magnetic_Field_Pos_Z_Getter Bg_B_Pos_Z,
        const Mass_Density_Flux_Getter Mas_f,
        const Momentum_Density_Flux_Getter Mom_f,
        const Total_Energy_Density_Flux_Getter Nrj_f,
        const Magnetic_Field_Flux_Getter Mag_f
    ) {
    if (verbose and grid.get_rank() == 0) {
        std::cout << "Setting default MHD state... ";
        std::cout.flush();
    }
    // set default state
    for (const auto cell_id: cells) {
        auto* const cell_data = grid[cell_id];
        if (cell_data == nullptr) {
            std::cerr <<  __FILE__ << "(" << __LINE__ << ") No data for cell: "
                      << cell_id
                      << std::endl;
            abort();
        }

        // zero fluxes and background fields
        Mas_f(*cell_data)         =
            Nrj_f(*cell_data)         =
                Mom_f(*cell_data)[0]      =
                    Mom_f(*cell_data)[1]      =
                        Mom_f(*cell_data)[2]      =
                            Mag_f(*cell_data)[0]      =
                                Mag_f(*cell_data)[1]      =
                                    Mag_f(*cell_data)[2]      = 0;

        const auto c = grid.geometry.get_center(cell_id);
        const auto r = sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
        const auto
        lat = asin(c[2] / r),
        lon = atan2(c[1], c[0]);

        const auto mass_density
            = proton_mass
              * initial_conditions.get_default_data(
                  Number_Density(),
                  time,
                  c[0], c[1], c[2],
                  r, lat, lon
              );
        const auto velocity
            = initial_conditions.get_default_data(
                  Velocity(),
                  time,
                  c[0], c[1], c[2],
                  r, lat, lon
              );
        const auto pressure
            = initial_conditions.get_default_data(
                  Pressure(),
                  time,
                  c[0], c[1], c[2],
                  r, lat, lon
              );
        const auto magnetic_field
            = initial_conditions.get_default_data(
                  Magnetic_Field(),
                  time,
                  c[0], c[1], c[2],
                  r, lat, lon
              );

        Mas(*cell_data) = mass_density;
        Mom(*cell_data) = mass_density * velocity;
        Mag(*cell_data) = magnetic_field;
        Nrj(*cell_data) = get_total_energy_density(
                              mass_density,
                              velocity,
                              pressure,
                              magnetic_field,
                              adiabatic_index,
                              vacuum_permeability
                          );

        const auto cell_end = grid.geometry.get_max(cell_id);
        Bg_B_Pos_X(*cell_data) = bg_B.get_background_field(
        {cell_end[0], c[1], c[2]},
        vacuum_permeability
        );
        Bg_B_Pos_Y(*cell_data) = bg_B.get_background_field(
        {c[0], cell_end[1], c[2]},
        vacuum_permeability
        );
        Bg_B_Pos_Z(*cell_data) = bg_B.get_background_field(
        {c[0], c[1], cell_end[2]},
        vacuum_permeability
        );
    }

    // set non-default initial conditions
    if (verbose and grid.get_rank() == 0) {
        std::cout << "done\nSetting non-default initial MHD state... ";
        std::cout.flush();
    }

    /*
    Set non-default initial conditions
    */

    // mass density
    for (
        size_t i = 0;
        i < initial_conditions.get_number_of_regions(Number_Density());
        i++
    ) {
        const auto& init_cond = initial_conditions.get_initial_condition(Number_Density(), i);
        const auto& geometry_id = init_cond.get_geometry_id();
        const auto& cells = geometries.get_cells(geometry_id);
        for (const auto& cell: cells) {
            const auto c = grid.geometry.get_center(cell);
            const auto r = sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
            const auto
            lat = asin(c[2] / r),
            lon = atan2(c[1], c[0]);

            const auto mass_density
                = proton_mass
                  * initial_conditions.get_data(
                      Number_Density(),
                      geometry_id,
                      time,
                      c[0], c[1], c[2],
                      r, lat, lon
                  );

            auto* const cell_data = grid[cell];
            if (cell_data == NULL) {
                std::cerr <<  __FILE__ << "(" << __LINE__ << std::endl;
                abort();
            }

            Mas(*cell_data) = mass_density;
        }
    }

    // velocity
    for (
        size_t i = 0;
        i < initial_conditions.get_number_of_regions(Velocity());
        i++
    ) {
        const auto& init_cond = initial_conditions.get_initial_condition(Velocity(), i);
        const auto& geometry_id = init_cond.get_geometry_id();
        const auto& cells = geometries.get_cells(geometry_id);
        for (const auto& cell: cells) {
            const auto c = grid.geometry.get_center(cell);
            const auto r = sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
            const auto
            lat = asin(c[2] / r),
            lon = atan2(c[1], c[0]);

            const auto velocity = initial_conditions.get_data(
                                      Velocity(),
                                      geometry_id,
                                      time,
                                      c[0], c[1], c[2],
                                      r, lat, lon
                                  );

            auto* const cell_data = grid[cell];
            if (cell_data == NULL) {
                std::cerr <<  __FILE__ << "(" << __LINE__
                          << ") No data for cell: " << cell
                          << std::endl;
                abort();
            }

            Mom(*cell_data) = Mas(*cell_data) * velocity;
        }
    }

    // magnetic field
    for (
        size_t i = 0;
        i < initial_conditions.get_number_of_regions(Magnetic_Field());
        i++
    ) {
        const auto& init_cond = initial_conditions.get_initial_condition(Magnetic_Field(), i);
        const auto& geometry_id = init_cond.get_geometry_id();
        const auto& cells = geometries.get_cells(geometry_id);
        for (const auto& cell: cells) {
            const auto c = grid.geometry.get_center(cell);
            const auto r = sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
            const auto
            lat = asin(c[2] / r),
            lon = atan2(c[1], c[0]);

            const auto magnetic_field = initial_conditions.get_data(
                                            Magnetic_Field(),
                                            geometry_id,
                                            time,
                                            c[0], c[1], c[2],
                                            r, lat, lon
                                        );

            auto* const cell_data = grid[cell];
            if (cell_data == NULL) {
                std::cerr <<  __FILE__ << "(" << __LINE__
                          << ") No data for cell: " << cell
                          << std::endl;
                abort();
            }

            Mag(*cell_data) = magnetic_field;
        }
    }

    // pressure
    for (
        size_t i = 0;
        i < initial_conditions.get_number_of_regions(Pressure());
        i++
    ) {
        std::cout << std::endl;
        const auto& init_cond = initial_conditions.get_initial_condition(Pressure(), i);
        const auto& geometry_id = init_cond.get_geometry_id();
        std::cout << geometry_id << std::endl;
        const auto& cells = geometries.get_cells(geometry_id);
        std::cout << cells.size() << std::endl;
        for (const auto& cell: cells) {
            const auto c = grid.geometry.get_center(cell);
            const auto r = sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
            const auto
            lat = asin(c[2] / r),
            lon = atan2(c[1], c[0]);

            const auto pressure = initial_conditions.get_data(
                                      Pressure(),
                                      geometry_id,
                                      time,
                                      c[0], c[1], c[2],
                                      r, lat, lon
                                  );

            auto* const cell_data = grid[cell];
            if (cell_data == NULL) {
                std::cerr <<  __FILE__ << "(" << __LINE__
                          << ") No data for cell: " << cell
                          << std::endl;
                abort();
            }

            Nrj(*cell_data) = get_total_energy_density(
                                  Mas(*cell_data),
                                  Mom(*cell_data) / Mas(*cell_data),
                                  pressure,
                                  Mag(*cell_data),
                                  adiabatic_index,
                                  vacuum_permeability
                              );
        }
    }

    if (verbose and grid.get_rank() == 0) {
        std::cout << "done" << std::endl;
    }
}
예제 #4
0
> void initialize_field(
	Init_Cond& init_cond,
	dccrg::Dccrg<Cell, Geometry>& grid,
	const std::vector<uint64_t>& cells,
	const double time,
	const Magnetic_Field_Getter Mag
) {
	// set default state
	for (const auto cell_id: cells) {
		const auto
			cell_start = grid.geometry.get_min(cell_id),
			cell_end = grid.geometry.get_max(cell_id),
			cell_center = grid.geometry.get_center(cell_id);

		init_cond.add_cell(
			cell_id,
			cell_start,
			cell_end
		);

		auto* const cell_data = grid[cell_id];
		if (cell_data == NULL) {
			std::cerr <<  __FILE__ << "(" << __LINE__ << ") No data for cell: "
				<< cell_id
				<< std::endl;
			abort();
		}

		try {
			Mag(*cell_data)
				= init_cond.default_data.get_data(
					mhd::Magnetic_Field(),
					cell_center,
					time
				);
		} catch (mup::ParserError& e) {
			std::cout << "Couldn't get magnetic field for default initial condition." << std::endl;
			throw;
		}
	}

	// set non-default initial conditions
	for (size_t bdy_i = 0; bdy_i < init_cond.get_number_of_boundaries(); bdy_i++) {
		const auto& boundary_cells = init_cond.get_cells(bdy_i);

		for (const auto& cell_id: boundary_cells) {
			const auto cell_center = grid.geometry.get_center(cell_id);

			auto* const cell_data = grid[cell_id];
			if (cell_data == NULL) {
				std::cerr <<  __FILE__ << "(" << __LINE__ << ") No data for cell: "
					<< cell_id
					<< std::endl;
				abort();
			}

			try {
				Mag(*cell_data)
					= init_cond.get_data(
						mhd::Magnetic_Field(),
						bdy_i,
						cell_center,
						time
					);
			} catch (mup::ParserError& e) {
				std::cout << "Couldn't get magnetic field for default initial condition." << std::endl;
				throw;
			}
		}
	}
}