void populate_system(System& system, Foundation const& foundation, HamiltonianIndices const& hamiltonian_indices) { auto const size = hamiltonian_indices.size(); system.positions.resize(size); system.sublattices.resize(size); system.hoppings.resize(size, size); auto const& lattice = foundation.get_lattice(); auto const reserve_nonzeros = (lattice.max_hoppings() * size) / 2; auto matrix_view = compressed_inserter(system.hoppings, reserve_nonzeros); for (auto const& site : foundation) { auto const index = hamiltonian_indices[site]; if (index < 0) continue; // invalid site system.positions[index] = site.get_position(); system.sublattices[index] = lattice[site.get_sublattice()].alias; matrix_view.start_row(index); site.for_each_neighbour([&](Site neighbor, Hopping hopping) { auto const neighbor_index = hamiltonian_indices[neighbor]; if (neighbor_index < 0) return; // invalid if (!hopping.is_conjugate) // only make half the matrix, other half is the conjugate matrix_view.insert(neighbor_index, hopping.id); }); } matrix_view.compress(); }
void populate_boundaries(System& system, Foundation const& foundation, HamiltonianIndices const& hamiltonian_indices, TranslationalSymmetry const& symmetry) { // a boundary is added first to prevent copying of Eigen::SparseMatrix // --> revise when Eigen types become movable auto const size = hamiltonian_indices.size(); auto const& lattice = foundation.get_lattice(); system.boundaries.emplace_back(); for (const auto& translation : symmetry.translations(foundation)) { auto& boundary = system.boundaries.back(); boundary.shift = translation.shift_lenght; boundary.hoppings.resize(size, size); // the reservation number is intentionally overestimated auto const reserve_nonzeros = [&]{ auto nz = static_cast<int>(lattice.sublattices.size() * lattice.max_hoppings() / 2); for (auto i = 0; i < translation.boundary_slice.ndims(); ++i) { if (translation.boundary_slice[i].end < 0) nz *= foundation.get_size()[i]; } return nz; }(); auto boundary_matrix_view = compressed_inserter(boundary.hoppings, reserve_nonzeros); for (auto const& site : foundation[translation.boundary_slice]) { if (!site.is_valid()) continue; boundary_matrix_view.start_row(hamiltonian_indices[site]); auto const shifted_site = site.shifted(translation.shift_index); // the site is shifted to the opposite edge of the translation unit shifted_site.for_each_neighbour([&](Site neighbor, Hopping hopping) { auto const neighbor_index = hamiltonian_indices[neighbor]; if (neighbor_index < 0) return; // invalid boundary_matrix_view.insert(neighbor_index, hopping.id); }); } boundary_matrix_view.compress(); if (boundary.hoppings.nonZeros() > 0) system.boundaries.emplace_back(); } system.boundaries.pop_back(); }
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data, const std::vector<PlayerSaveGameData>& player_save_game_data, const Universe& universe, const EmpireManager& empire_manager, const SpeciesManager& species_manager, const CombatLogManager& combat_log_manager, const GalaxySetupData& galaxy_setup_data, bool multiplayer) { ScopedTimer timer("SaveGame: " + filename, true); bool use_binary = GetOptionsDB().Get<bool>("binary-serialization"); DebugLogger() << "SaveGame(" << (use_binary ? "binary" : "zlib-xml") << ") filename: " << filename; GetUniverse().EncodingEmpire() = ALL_EMPIRES; DebugLogger() << "Compiling save empire and preview data"; std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager); SaveGamePreviewData save_preview_data; CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data); // reinterpret save game data as header data for uncompressed header std::vector<PlayerSaveHeaderData> player_save_header_data; for (std::vector<PlayerSaveGameData>::const_iterator it = player_save_game_data.begin(); it != player_save_game_data.end(); ++it) { player_save_header_data.push_back(*it); } try { fs::path path = FilenameToPath(filename); // A relative path should be relative to the save directory. if (path.is_relative()) { path = GetSaveDir()/path; DebugLogger() << "Made save path relative to save dir. Is now: " << path; } if (multiplayer) { // Make sure the path points into our save directory if (!IsInside(path, GetSaveDir())) { path = GetSaveDir() / path.filename(); } } // set up output archive / stream for saving fs::ofstream ofs(path, std::ios_base::binary); if (!ofs) throw std::runtime_error(UNABLE_TO_OPEN_FILE); if (use_binary) { DebugLogger() << "Creating binary oarchive"; freeorion_bin_oarchive boa(ofs); boa << BOOST_SERIALIZATION_NVP(save_preview_data); boa << BOOST_SERIALIZATION_NVP(galaxy_setup_data); boa << BOOST_SERIALIZATION_NVP(server_save_game_data); boa << BOOST_SERIALIZATION_NVP(player_save_header_data); boa << BOOST_SERIALIZATION_NVP(empire_save_game_data); boa << BOOST_SERIALIZATION_NVP(player_save_game_data); boa << BOOST_SERIALIZATION_NVP(empire_manager); boa << BOOST_SERIALIZATION_NVP(species_manager); boa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(boa, universe); DebugLogger() << "Done serializing"; } else { // Two-tier serialization: // main archive is uncompressed serialized header data first // then contains a string for compressed second archive // that contains the main gamestate info // allocate buffers for serialized gamestate DebugLogger() << "Allocating buffers for XML serialization..."; std::string serial_str, compressed_str; try { serial_str.reserve( std::pow(2.0, 29.0)); compressed_str.reserve(std::pow(2.0, 26.0)); } catch (...) { DebugLogger() << "Unable to preallocate full serialization buffers. Attempting serialization with dynamic buffer allocation."; } // wrap buffer string in iostream::stream to receive serialized data typedef boost::iostreams::back_insert_device<std::string> InsertDevice; InsertDevice serial_inserter(serial_str); boost::iostreams::stream<InsertDevice> s_sink(serial_inserter); // create archive with (preallocated) buffer... freeorion_xml_oarchive xoa(s_sink); // serialize main gamestate info xoa << BOOST_SERIALIZATION_NVP(player_save_game_data); xoa << BOOST_SERIALIZATION_NVP(empire_manager); xoa << BOOST_SERIALIZATION_NVP(species_manager); xoa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(xoa, universe); s_sink.flush(); // wrap gamestate string in iostream::stream to extract serialized data typedef boost::iostreams::basic_array_source<char> SourceDevice; SourceDevice source(serial_str.data(), serial_str.size()); boost::iostreams::stream<SourceDevice> s_source(source); // wrap compresed buffer string in iostream::streams to receive compressed string InsertDevice compressed_inserter(compressed_str); boost::iostreams::stream<InsertDevice> c_sink(compressed_inserter); // compression-filter gamestate into compressed string boost::iostreams::filtering_ostreambuf o; o.push(boost::iostreams::zlib_compressor()); o.push(c_sink); boost::iostreams::copy(s_source, o); c_sink.flush(); // write to save file: uncompressed header serialized data, with compressed main archive string at end... freeorion_xml_oarchive xoa2(ofs); // serialize uncompressed save header info xoa2 << BOOST_SERIALIZATION_NVP(save_preview_data); xoa2 << BOOST_SERIALIZATION_NVP(galaxy_setup_data); xoa2 << BOOST_SERIALIZATION_NVP(server_save_game_data); xoa2 << BOOST_SERIALIZATION_NVP(player_save_header_data); xoa2 << BOOST_SERIALIZATION_NVP(empire_save_game_data); // append compressed gamestate info xoa2 << BOOST_SERIALIZATION_NVP(compressed_str); } } catch (const std::exception& e) { ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what(); throw e; } DebugLogger() << "SaveGame : Successfully wrote save file"; }
System::Port::Port(Foundation const& foundation, HamiltonianIndices const& hamiltonian_indices, Lead const& lead) { auto const& lattice = foundation.get_lattice(); shift = static_cast<float>(-lead.sign) * lattice.vectors[lead.axis]; auto const junction = LeadJunction(foundation, lead); auto const slice = foundation[junction.slice_index]; indices = [&]{ auto indices = std::vector<int>(); indices.reserve(junction.is_valid.count()); for (auto const& site : slice) { if (junction.is_valid[site.get_slice_idx()]) { indices.push_back(hamiltonian_indices[site]); } } return indices; }(); inner_hoppings = [&]{ auto const size = static_cast<int>(indices.size()); auto matrix = SparseMatrixX<hop_id>(size, size); auto matrix_view = compressed_inserter(matrix, size * lattice.max_hoppings()); for (auto const& site : slice) { if (!junction.is_valid[site.get_slice_idx()]) { continue; } matrix_view.start_row(); site.for_each_neighbour([&](Site neighbor, Hopping hopping) { auto const index = lead_index(hamiltonian_indices[neighbor]); if (index >= 0) { matrix_view.insert(index, hopping.id); } }); } matrix_view.compress(); return matrix; }(); outer_hoppings = [&]{ auto const size = static_cast<int>(indices.size()); auto matrix = SparseMatrixX<hop_id>(size, size); auto matrix_view = compressed_inserter(matrix, size * lattice.max_hoppings()); for (auto const& site : slice) { if (!junction.is_valid[site.get_slice_idx()]) { continue; } auto const shifted_site = [&]{ Index3D shift_index = Index3D::Zero(); shift_index[lead.axis] = lead.sign; return site.shifted(shift_index); }(); matrix_view.start_row(); shifted_site.for_each_neighbour([&](Site neighbor, Hopping hopping) { auto const index = lead_index(hamiltonian_indices[neighbor]); if (index >= 0) { matrix_view.insert(index, hopping.id); } }); } matrix_view.compress(); return matrix; }(); }