std::string GenerateNbInteractionTypesFunction(Model &model) { std::stringstream stream; stream << "InteractionType NbInteractionTypes() {\n" << "\treturn " << model.GetInteractions().size() << ";\n" << "}\n"; return stream.str(); }
std::string GenerateAttributesStruct(Model &model) { std::stringstream stream; for (const auto &agent : model.GetAgents()) { stream << agent.second.AttributesStruct(agent.first); stream << agent.second.PublicAttributesStruct(agent.first); stream << agent.second.CriticalAttributesStruct(agent.first); stream << agent.second.MessageStruct(agent.first); } for (const auto &interaction : model.GetInteractions()) { stream << interaction.second.AttributesStruct(interaction.first); stream << interaction.second.MessageStruct(interaction.first); } return stream.str(); }
std::string GenerateInteractionsMPIDatatypesFunction(Model &model, clang::ASTContext *context) { std::stringstream stream; // Add prototype stream << "size_t CreateInteractionsMPIDatatypes(std::unordered_map<InteractionType, MPI_Datatype> &interactions_MPI_types) {\n" << "\tstd::vector<int> lengths; " << "std::vector<MPI_Aint> offsets; " << "std::vector<MPI_Datatype> mpi_types;\n" << "\tMPI_Datatype t;\n" << "\tsize_t max_size = 0;\n"; std::unordered_set<std::string> temp_database; temp_database.insert("t"); for (const auto &interaction : model.GetInteractions()) { int n_fields = interaction.second.GetFields().size(); std::map<int64_t, std::string> type_temporaries; int i = 0; // Construct the data types of the fields for (const auto &field : interaction.second.GetFields()) { std::string temp = "t" + std::to_string(i); if (!temp_database.count(temp)) { stream << "\tMPI_Datatype " << temp << ";\n"; temp_database.insert(temp); } std::string code_field = GenerateCodeMPIDatatype(field.second.GetType(), context, temp, temp_database); if (code_field.substr(0,6) != "MPI_Da" && code_field.substr(0,3) == "MPI") // No temporary to use type_temporaries[field.second.GetId()] = code_field; else { type_temporaries[field.second.GetId()] = temp; stream << code_field; } i++; } // Now construct the corresponding struct MPI_Datatype stream << "\tlengths = {"; for (int j = 0; j < n_fields; j++) stream << "1,"; if (n_fields > 0) stream.seekp(-1,std::ios_base::cur); stream << "};\n"; stream << "\toffsets = {"; for (const auto &field : interaction.second.GetFields()) { stream << "offsetof(" << interaction.first << "Attrs" << "," << field.first << "),"; } if (n_fields > 0) stream.seekp(-1,std::ios_base::cur); stream << "};\n"; stream << "\tmpi_types = {"; for (const auto &field : interaction.second.GetFields()) { stream << type_temporaries[field.second.GetId()] <<","; } if (n_fields > 0) stream.seekp(-1,std::ios_base::cur); stream << "};\n"; stream << "\tMPI_Type_create_struct(" << n_fields << ", lengths.data(), offsets.data(), mpi_types.data(), &t);\n" << "\tMPI_Type_commit(&t);\n"; // Now the MPI_Datatype of the message structure // i.e. we add the type and the id and types of the sender and recipient stream << "\tlengths = {1,1,1,1,1,1};\n" << "\toffsets = {offsetof(" << interaction.first << "MessageStruct,type)," << "offsetof(" << interaction.first << "MessageStruct,sender_id),\n" << "\t offsetof(" << interaction.first << "MessageStruct,sender_type)," << "offsetof(" << interaction.first << "MessageStruct,recipient_id),\n" << "\t offsetof(" << interaction.first << "MessageStruct,recipient_type)," << "offsetof(" << interaction.first << "MessageStruct,data)}" << ";\n"; stream << "\tmpi_types = {MPI_UINT64_T,MPI_UINT64_T,MPI_UINT64_T,MPI_UINT64_T,MPI_UINT64_T,t};\n"; stream << "\tMPI_Type_create_struct(" << "6" << ", lengths.data(), offsets.data(), mpi_types.data(), &t);\n" << "\tMPI_Type_commit(&t);\n"; // Free the intermediary generated MPI_Datatypes for (const auto &temporary : type_temporaries) { if (temporary.second.length() > 0 && temporary.second.substr(0,1) == "t") // if it represents a constructed MPI_Datatype, free it stream << "\tMPI_Type_free(&" << temporary.second <<");\n"; } // Store the MPI_Datatype stream << "\tinteractions_MPI_types[" << interaction.second.GetId() << "] = t;\n"; // Update the maximum size stream << "\tif (sizeof(" << interaction.first << "MessageStruct) > max_size)" << " {max_size = sizeof(" << interaction.first << "MessageStruct);}\n"; } stream << "\treturn max_size;\n" << "}\n"; return stream.str(); }