From 66f5bd67d46a87d0d830fe4fa7e6e8f91daddf23 Mon Sep 17 00:00:00 2001 From: jcschaff Date: Sat, 1 Jun 2024 21:14:48 -0400 Subject: [PATCH] create pyvcell_fvsolver Python module using pybind11 and vcell library --- CMakeLists.txt | 67 ++++++--------- pyvcell-fvsolver/CMakeLists.txt | 14 +-- pyvcell-fvsolver/include/SolverMain.h | 13 +++ pyvcell-fvsolver/include/add.h | 10 --- pyvcell-fvsolver/src/SolverMain.cpp | 100 ++++++++++++++++++++++ pyvcell-fvsolver/src/add.cpp | 6 -- pyvcell-fvsolver/src/example.cpp | 10 --- pyvcell-fvsolver/src/pyvcell_fvsolver.cpp | 13 +++ 8 files changed, 163 insertions(+), 70 deletions(-) create mode 100644 pyvcell-fvsolver/include/SolverMain.h delete mode 100644 pyvcell-fvsolver/include/add.h create mode 100644 pyvcell-fvsolver/src/SolverMain.cpp delete mode 100644 pyvcell-fvsolver/src/add.cpp delete mode 100644 pyvcell-fvsolver/src/example.cpp create mode 100644 pyvcell-fvsolver/src/pyvcell_fvsolver.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fbd8f630..fd9670c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,8 @@ endif() cmake_minimum_required(VERSION 3.13...3.27) project(fvsolver) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) enable_language(CXX) enable_language(C) enable_language(Fortran) @@ -95,6 +96,8 @@ include (FindZLIB) option(OPTION_TARGET_MESSAGING "Messaging (requires libcurl)" off) option(OPTION_TARGET_DOCS "Generate Doxygen documentation" on) option(OPTION_TARGET_FV_SOLVER on) +option(OPTION_TARGET_MESSAGING "Messaging (requires libcurl)" off) + if (${OPTION_TARGET_DOCS}) # if (DOXYGEN_FOUND AND ${CMAKE_VERSION} GREATER_EQUAL 3.9) @@ -213,47 +216,33 @@ endif() add_subdirectory(VCellMessaging) - if (${OPTION_TARGET_FV_SOLVER}) - add_subdirectory(VCellZipUtils) - add_subdirectory(libzip-1.2.0) - endif() - - if (${OPTION_TARGET_FV_SOLVER}) - message(STATUS "adding ExpressionParser") - add_subdirectory(ExpressionParser) - endif() + add_subdirectory(VCellZipUtils) - if (${OPTION_TARGET_FV_SOLVER} - ) - message(STATUS "adding sundials") - add_subdirectory(sundials) - endif () - - if (${OPTION_TARGET_FV_SOLVER}) - if (NOT APPLE) - add_subdirectory(blas) - endif() + add_subdirectory(libzip-1.2.0) + + add_subdirectory(ExpressionParser) + + add_subdirectory(sundials) + + if (NOT APPLE) + add_subdirectory(blas) endif() - if (OPTION_TARGET_FV_SOLVER) - option(OPTION_VCELL "Compile Smoldyn for VCell" ON) - option(OPTION_NSV "Compile Smoldyn with NextSubvolume functionality" OFF) - option(OPTION_USE_OPENGL "Build with OpenGL support" OFF) - option(OPTION_USE_ZLIB "Build with Zlib support" ON) - option(OPTION_USE_LIBTIFF "Build with LibTiff support" OFF) - option(OPTION_USE_ICONV "Build with Libiconv support" OFF) - SET(HAVE_ZLIB TRUE) - set(OPTION_TARGET_LIBSMOLDYN ON) - set(OPTION_VCELL ON) - add_subdirectory(bridgeVCellSmoldyn) - add_subdirectory(smoldyn-2.38) - endif () - - if (${OPTION_TARGET_FV_SOLVER}) - add_subdirectory(VCell) - add_subdirectory(PCGPack) - add_subdirectory(qhull) - endif () + option(OPTION_VCELL "Compile Smoldyn for VCell" ON) + option(OPTION_NSV "Compile Smoldyn with NextSubvolume functionality" OFF) + option(OPTION_USE_OPENGL "Build with OpenGL support" OFF) + option(OPTION_USE_ZLIB "Build with Zlib support" ON) + option(OPTION_USE_LIBTIFF "Build with LibTiff support" OFF) + option(OPTION_USE_ICONV "Build with Libiconv support" OFF) + SET(HAVE_ZLIB TRUE) + set(OPTION_TARGET_LIBSMOLDYN ON) + set(OPTION_VCELL ON) + add_subdirectory(bridgeVCellSmoldyn) + add_subdirectory(smoldyn-2.38) + + add_subdirectory(VCell) + add_subdirectory(PCGPack) + add_subdirectory(qhull) add_subdirectory(extern/pybind11) add_subdirectory(pyvcell-fvsolver) diff --git a/pyvcell-fvsolver/CMakeLists.txt b/pyvcell-fvsolver/CMakeLists.txt index 1bc03c0a..b610f649 100644 --- a/pyvcell-fvsolver/CMakeLists.txt +++ b/pyvcell-fvsolver/CMakeLists.txt @@ -1,14 +1,18 @@ -project(example) +project(pyvcell_fvsolver) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) set(HEADER_FILES - include/add.h + include/SolverMain.h ) set(SOURCE_FILES - src/add.cpp - src/example.cpp + src/pyvcell_fvsolver.cpp + src/SolverMain.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -pybind11_add_module(example ${SOURCE_FILES} ${HEADER_FILES}) +pybind11_add_module(pyvcell_fvsolver ${SOURCE_FILES} ${HEADER_FILES}) + +target_link_libraries(pyvcell_fvsolver PRIVATE vcell) diff --git a/pyvcell-fvsolver/include/SolverMain.h b/pyvcell-fvsolver/include/SolverMain.h new file mode 100644 index 00000000..5b69637f --- /dev/null +++ b/pyvcell-fvsolver/include/SolverMain.h @@ -0,0 +1,13 @@ +// +// Created by Jim Schaff on 6/1/24. +// + +#ifndef SOLVERMAIN_H +#define SOLVERMAIN_H + +#include + +std::string version(); +int solve(const std::string& inputFilename, const std::string& outputDir); + +#endif //SOLVERMAIN_H diff --git a/pyvcell-fvsolver/include/add.h b/pyvcell-fvsolver/include/add.h deleted file mode 100644 index 2057d227..00000000 --- a/pyvcell-fvsolver/include/add.h +++ /dev/null @@ -1,10 +0,0 @@ -// -// Created by Jim Schaff on 5/27/24. -// - -#ifndef ADD_H -#define ADD_H - -int add(int i, int j); - -#endif //ADD_H diff --git a/pyvcell-fvsolver/src/SolverMain.cpp b/pyvcell-fvsolver/src/SolverMain.cpp new file mode 100644 index 00000000..5e5b1527 --- /dev/null +++ b/pyvcell-fvsolver/src/SolverMain.cpp @@ -0,0 +1,100 @@ +// +// Created by Jim Schaff on 6/1/24. +// +#include "SolverMain.h" + +#include +#include +#include +#include +using namespace std; + +#undef USE_MESSAGING + +#include +#include +#include +#include +#include +#include +#include + + + +void vcellExit(int returnCode, string& errorMsg) { + if (SimulationMessaging::getInstVar() == 0) { + if (returnCode != 0) { + cerr << errorMsg << endl; + } + } else if (!SimulationMessaging::getInstVar()->isStopRequested()) { + if (returnCode != 0) { + SimulationMessaging::getInstVar()->setWorkerEvent(new WorkerEvent(JOB_FAILURE, errorMsg.c_str())); + } + } +} + +std::string version() +{ + return "Finite Volume version " + std::string(g_GIT_DESCRIBE) + " with smoldyn version " + std::string(VERSION); +} + +int solve(const std::string& inputFilename, const std::string& outputDir) { + // Check if output directory exists, if not create it + std::filesystem::path dirPath(outputDir); + if (!std::filesystem::exists(dirPath)) { + std::filesystem::create_directories(dirPath); + } + + // Open the input file + std::ifstream inputFile(inputFilename); + if (!inputFile.is_open()) { + throw std::runtime_error("Could not open input file: " + inputFilename); + } + + vcellhybrid::setHybrid(); //get smoldyn library in correct state + int returnCode = 0; + string errorMsg = "Exception : "; + + bool bSimZip = true; + int taskID = 0; + + SimulationMessaging::create(); + + FVSolver* fvSolver = nullptr; + + try { + fvSolver = new FVSolver(inputFile, taskID, outputDir.c_str(), bSimZip); + + inputFile.close(); + + if(fvSolver->getNumVariables() == 0){ + //sims with no reactions and no diffusing species cause exit logic to 'wait' forever + //never sending a job failed or job finished message and never cleaning up threads + throw invalid_argument("FiniteVolume error: Must have at least 1 variable or reaction to solve"); + } + fvSolver->solve(); + + } catch (const char *exStr){ + errorMsg += exStr; + returnCode = 1; + } catch (string& exStr){ + errorMsg += exStr; + returnCode = 1; + } catch (VCell::Exception& ex){ + errorMsg += ex.getMessage(); + returnCode = 1; + } catch (std::exception & e) { + errorMsg += e.what(); + returnCode = 1; + } catch (...){ + errorMsg += "unknown error"; + returnCode = 1; + } + + if (inputFile.is_open()) { + inputFile.close(); + } + vcellExit(returnCode, errorMsg); + delete fvSolver; + return returnCode; +} diff --git a/pyvcell-fvsolver/src/add.cpp b/pyvcell-fvsolver/src/add.cpp deleted file mode 100644 index d70770b1..00000000 --- a/pyvcell-fvsolver/src/add.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "add.h" - -int add(int i, int j) { - return i + j; -} - diff --git a/pyvcell-fvsolver/src/example.cpp b/pyvcell-fvsolver/src/example.cpp deleted file mode 100644 index fe053be6..00000000 --- a/pyvcell-fvsolver/src/example.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include <../../extern/pybind11/include/pybind11/pybind11.h> -#include "add.h" - -namespace py = pybind11; - -PYBIND11_MODULE(example, m) { - m.doc() = "pybind11 example plugin"; // optional module docstring - - m.def("add", &add, "A function that adds two numbers", py::arg("i"), py::arg("j")); -} diff --git a/pyvcell-fvsolver/src/pyvcell_fvsolver.cpp b/pyvcell-fvsolver/src/pyvcell_fvsolver.cpp new file mode 100644 index 00000000..8cd13223 --- /dev/null +++ b/pyvcell-fvsolver/src/pyvcell_fvsolver.cpp @@ -0,0 +1,13 @@ +#include <../../extern/pybind11/include/pybind11/pybind11.h> + +#include "SolverMain.h" + +namespace py = pybind11; + +PYBIND11_MODULE(pyvcell_fvsolver, m) { + m.doc() = "VCell FiniteVolume plugin"; // optional module docstring + + m.def("version", &version, "A function that returns the version of the FiniteVolume solver"); + + m.def("solve", &solve, "A function that invokes the FiniteVolume solver", py::arg("inputFilename"), py::arg("outputDir")); +}