diff --git a/modules/services/slurm.nix b/modules/services/slurm.nix index eafd6318..99b11b1c 100644 --- a/modules/services/slurm.nix +++ b/modules/services/slurm.nix @@ -291,9 +291,10 @@ inputs: }) slurm.tui.cpuQueues; } - // (if slurm.tui.gpuQueues == null then {} else + // (if slurm.tui.gpuQueues == null then {} else rec { VaspGpu.Queue = builtins.map (queue: { Name = queue.name; Gpu = queue.gpuIds; }) slurm.tui.gpuQueues; + Mumax3 = VaspGpu; }); })); })]; diff --git a/packages/sbatch-tui/CMakeLists.txt b/packages/sbatch-tui/CMakeLists.txt index 99633823..fd47bbca 100644 --- a/packages/sbatch-tui/CMakeLists.txt +++ b/packages/sbatch-tui/CMakeLists.txt @@ -12,7 +12,7 @@ endif() find_package(ftxui REQUIRED) find_package(biu REQUIRED) -add_executable(sbatch-tui src/main.cpp src/vasp_gpu.cpp src/vasp_cpu.cpp) +add_executable(sbatch-tui src/main.cpp src/vasp_gpu.cpp src/vasp_cpu.cpp src/mumax3.cpp) target_compile_features(sbatch-tui PUBLIC cxx_std_23) target_link_libraries(sbatch-tui PRIVATE ftxui::screen ftxui::dom ftxui::component biu::biu) target_include_directories(sbatch-tui PRIVATE $) diff --git a/packages/sbatch-tui/sbatch-tui.yaml b/packages/sbatch-tui/sbatch-tui.yaml index e26b2cb2..fcee162d 100644 --- a/packages/sbatch-tui/sbatch-tui.yaml +++ b/packages/sbatch-tui/sbatch-tui.yaml @@ -10,3 +10,7 @@ Program: Queue: - Name: localhost Gpu: [ "4060" ] + Mumax3: + Queue: + - Name: localhost + Gpu: [ "4060" ] diff --git a/packages/sbatch-tui/src/mumax3.cpp b/packages/sbatch-tui/src/mumax3.cpp index e69de29b..16a2f3a0 100644 --- a/packages/sbatch-tui/src/mumax3.cpp +++ b/packages/sbatch-tui/src/mumax3.cpp @@ -0,0 +1,127 @@ +# include + +namespace sbatch +{ + class Mumax3 : public Program + { + public: struct StateType + { + int QueueSelected = 0; + std::vector QueueEntries; + int GpuSchemeSelected = 0; + std::vector GpuSchemeEntries = { "Any", "Custom" }; + std::vector GpuSelected; + std::vector> GpuEntries; + bool Nomultithread = true; + int MemorySchemeSelected = 0; + std::vector MemorySchemeEntries = { "Default", "All", "Custom" }; + std::string Memory = "1"; + std::string JobName = std::filesystem::current_path().filename().string(); + std::string OutputFile = "output.txt"; + std::string InputFile = "input.txt"; + }; + protected: StateType State_; + public: virtual std::string get_name() const override { return "Mumax3"; } + public: virtual void load_config(YAML::Node node) override + { + for (auto queue : node["Queue"]) + { + State_.QueueEntries.push_back(queue["Name"].as()); + State_.GpuSelected.push_back(0); + State_.GpuEntries.push_back(queue["Gpu"].as>()); + } + } + public: virtual void try_load_state(YAML::Node node) noexcept override + { + try + { + auto saved_state = node.as(); + if (saved_state.QueueSelected < State_.QueueEntries.size()) State_.QueueSelected = saved_state.QueueSelected; + if (saved_state.GpuSchemeSelected < State_.GpuSchemeEntries.size()) + State_.GpuSchemeSelected = saved_state.GpuSchemeSelected; + if (saved_state.GpuSelected.size() == State_.GpuSelected.size()) + for (size_t i = 0; i < State_.GpuSelected.size(); i++) + if (saved_state.GpuSelected[i] < State_.GpuEntries[i].size()) + State_.GpuSelected[i] = saved_state.GpuSelected[i]; + State_.Nomultithread = saved_state.Nomultithread; + if (saved_state.MemorySchemeSelected < State_.MemorySchemeEntries.size()) + State_.MemorySchemeSelected = saved_state.MemorySchemeSelected; + State_.Memory = saved_state.Memory; + State_.OutputFile = saved_state.OutputFile; + State_.InputFile = saved_state.InputFile; + } + catch (...) {} + } + public: virtual YAML::Node save_state() const override { return YAML::Node(State_); } + public: virtual ftxui::Component get_interface() override + { + return ftxui::Container::Vertical + ({ + // 第一行 + ftxui::Container::Horizontal + ({ + // 队列 + ftxui::Menu(&State_.QueueEntries, &State_.QueueSelected) + | with_title("Queue:", ftxui::Color::GrayDark), + // GPU 设置,默认还是手动设置,如果手动的话,选定 GPU + ftxui::Container::Horizontal + ({ + ftxui::Menu(&State_.GpuSchemeEntries, &State_.GpuSchemeSelected), + ftxui::Container::Tab + ( + ranges::views::iota(0zu, State_.GpuEntries.size()) + | ranges::views::transform([&](auto i) + { return ftxui::Menu(&State_.GpuEntries[i], &State_.GpuSelected[i]); }) + | ranges::to_vector, + &State_.QueueSelected + ) | with_list_padding | with_separator + | ftxui::Maybe([&]{ return State_.GpuSchemeSelected == 1; }) + }) | with_title("GPU:", ftxui::Color::GrayDark) | with_separator, + // CPU 设置 + checkbox("Disable multithread", &State_.Nomultithread) + | with_title("CPU:", ftxui::Color::GrayDark) | with_separator, + // 内存 + ftxui::Container::Horizontal + ({ + ftxui::Menu(&State_.MemorySchemeEntries, &State_.MemorySchemeSelected), + input(&State_.Memory, "Memory (GB): ") + | with_list_padding | with_separator + | ftxui::Maybe([&]{ return State_.MemorySchemeSelected == 2; }) + }) | with_title("Memory:", ftxui::Color::GrayDark) | with_separator + }) | with_title("Resource allocation:") | with_bottom, + // 第三行:任务名和输入输出文件 + ftxui::Container::Vertical + ({ + input(&State_.JobName, "Job name: "), + input(&State_.InputFile, "Input file: "), + input(&State_.OutputFile, "Output file: "), + }) | with_title("Misc:") + }); + } + public: virtual std::string get_submit_command() const override + { + auto cpu_string = [&] + { return State_.Nomultithread ? " --hint=nomultithread" : ""; }(); + auto gpu_string = [&] + { + if (State_.GpuSchemeSelected == 0) return "--gpus=1"s; + else if (State_.GpuSchemeSelected == 1) return "--gpus={}:1"_f + (State_.GpuEntries[State_.QueueSelected][State_.GpuSelected[State_.QueueSelected]]); + else std::unreachable(); + }(); + auto mem_string = [&] + { + if (State_.MemorySchemeSelected == 0) return "--mem=24G"s; + else if (State_.MemorySchemeSelected == 1) return "--mem=0"s; + else if (State_.MemorySchemeSelected == 2) return "--mem={}G"_f(State_.Memory); + else std::unreachable(); + }(); + return "sbatch --partition={}\n{}{} {}\n--job-name='{}' --output='{}'\n--wrap=\"mumax3 {}\""_f + ( + State_.QueueEntries[State_.QueueSelected], gpu_string, cpu_string, mem_string, + State_.JobName, State_.OutputFile, State_.InputFile + ); + } + }; + template void Program::register_child_(); +}