From 251c665bd86e195abd36240743451907257f4b9b Mon Sep 17 00:00:00 2001 From: Ishaan Desai Date: Thu, 31 Oct 2024 13:52:01 +0100 Subject: [PATCH] Add documentation and test CI for pyFANS --- .github/workflows/test_pyfans.yaml | 38 +++++++++++++++++++ CMakeLists.txt | 8 ++-- pyfans/CMakeLists.txt | 2 +- pyfans/README.md | 15 ++++++++ pyfans/micro.cpp | 8 +--- test/test_pyfans/README.md | 17 +++++++++ test/test_pyfans/input.json | 31 +++++++++++++++ .../micro-manager-config-mech.json | 13 ------- .../{micro_mech.py => run_fans_as_library.py} | 0 9 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/test_pyfans.yaml create mode 100644 pyfans/README.md create mode 100644 test/test_pyfans/README.md create mode 100644 test/test_pyfans/input.json delete mode 100644 test/test_pyfans/micro-manager-config-mech.json rename test/test_pyfans/{micro_mech.py => run_fans_as_library.py} (100%) diff --git a/.github/workflows/test_pyfans.yaml b/.github/workflows/test_pyfans.yaml new file mode 100644 index 0000000..536dc2c --- /dev/null +++ b/.github/workflows/test_pyfans.yaml @@ -0,0 +1,38 @@ +name: Test PyFans + +on: [push, pull_request] + +jobs: + run-tests: + runs-on: ubuntu-latest + container: unistuttgartdae/fans-ci:noble + defaults: + run: + shell: "bash --login -eo pipefail {0}" + env: + FANS_BUILD_DIR: build + FANS_MPI_USER: fans + steps: + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Generate build directory + run: mkdir -p ${{ env.FANS_BUILD_DIR }} + + - name: Configure + working-directory: ${{ env.FANS_BUILD_DIR }} + run: | + cmake .. -DFANS_LIB=ON + make + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Run micro_mesh.py + run: | + pipx install numpy + cd test/test_pyfans + python run_fans_as_library.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 398e63a..5902eda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,11 +88,11 @@ find_package(MPI REQUIRED) find_package(FFTW3 REQUIRED COMPONENTS DOUBLE MPI) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(FANS_ENABLE_MICROMANAGER_DEFAULT ON) + set(FANS_LIB_DEFAULT OFF) endif () -option(FANS_ENABLE_MICROMANAGER "Enable python bindings for Micro Manager." ${FANS_ENABLE_MICROMANAGER_DEFAULT}) +option(FANS_LIB "Building FANS as a library to be used by the Micro Manager." ${FANS_LIB_DEFAULT}) -if (FANS_ENABLE_MICROMANAGER) +if (FANS_LIB) include(FetchContent) FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11.git @@ -129,7 +129,7 @@ add_custom_command( COMMENT "Create a symlink for FANS executable to ${CMAKE_CURRENT_SOURCE_DIR}/test/" ) -if (FANS_ENABLE_MICROMANAGER) +if (FANS_LIB) add_subdirectory(pyfans) endif () diff --git a/pyfans/CMakeLists.txt b/pyfans/CMakeLists.txt index 0273d32..6e7a683 100644 --- a/pyfans/CMakeLists.txt +++ b/pyfans/CMakeLists.txt @@ -6,7 +6,7 @@ add_custom_command( POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $ - ${CMAKE_CURRENT_SOURCE_DIR}/../test/$ + ${CMAKE_CURRENT_SOURCE_DIR}/../test/test_pyfans/$ COMMENT "Create a symlink for FANS python bindings to ${CMAKE_CURRENT_SOURCE_DIR}/../test/" ) diff --git a/pyfans/README.md b/pyfans/README.md new file mode 100644 index 0000000..2444e93 --- /dev/null +++ b/pyfans/README.md @@ -0,0 +1,15 @@ +# pyFANS + +pyFANS is a Python-wrapped library to control FANS via the [Micro Manager](https://precice.org/tooling-micro-manager-overview.html). The main idea is to create a large number of FANS simulations, and couple them to one macro-scale simulation typically in Abaqus, CalculiX, etc. The library follows the [API of the Micro Manager](https://precice.org/tooling-micro-manager-prepare-micro-simulation.html). + +## Dependencies + +- [pybind11](https://pybind11.readthedocs.io/en/stable/index.html) + +## Building + +To build FANS as a library, set the CMake variable `FANS_LIB` to `ON`. The CMake command to compile FANS would then be `cmake .. -DFANS_LIB=ON`. + +## Usage + +pyFANS is intended to be used with the Micro Manager and preCICE for two-scale coupled simulations. However, standalone use of the library is not restricted per se. Look at the [test_pyfans](../test/test_pyfans/) example to see how the library is used in a Python script. diff --git a/pyfans/micro.cpp b/pyfans/micro.cpp index f6b8981..f65e286 100644 --- a/pyfans/micro.cpp +++ b/pyfans/micro.cpp @@ -35,8 +35,8 @@ MicroSimulation::MicroSimulation(int sim_id) // initialize fftw mpi fftw_mpi_init(); - // Convert the input file path to char* and read the input file - const char *input_files_path = "input_files/test_LinearElastic.json"; + // Input file name is hardcoded. TODO: Make it configurable + const char *input_files_path = "input.json"; int input_files_path_length = strlen(input_files_path) + 1; in_place_temp_path = new char[input_files_path_length]; strcpy(in_place_temp_path, input_files_path); @@ -52,8 +52,6 @@ MicroSimulation::MicroSimulation(int sim_id) // Solve py::dict MicroSimulation::solve(py::dict macro_data, double dt) { - std::cout << "Solving micro problem" << std::endl; - // Create a pybind style Numpy array from macro_write_data["micro_vector_data"], which is a Numpy array py::array_t strain1 = macro_data["strains1to3"].cast>(); py::array_t strain2 = macro_data["strains4to6"].cast>(); @@ -83,8 +81,6 @@ py::dict MicroSimulation::solve(py::dict macro_data, double dt) auto C = solver->get_homogenized_tangent(pert_param); - std::cout << "Homogenized stiffness matrix C: " << C << std::endl; - // Convert data to a py::dict again to send it back to the Micro Manager py::dict micro_write_data; diff --git a/test/test_pyfans/README.md b/test/test_pyfans/README.md new file mode 100644 index 0000000..e3b0e2a --- /dev/null +++ b/test/test_pyfans/README.md @@ -0,0 +1,17 @@ +# Test pyFANS + +Test pyFANS as standalone library called from a Python script. + +## Build pyFANS + +Configure the FANS CMake build with the variable `FANS_LIB` set to `ON`. + +## Run the test + +Run + +```bash +python3 run_fans_as_library.py +``` + +The script creates a pyFANS object and calls the `solve()` method. The script only checks if the pyFANS object is created and the solve function is callable. The result is not checked for correctness. diff --git a/test/test_pyfans/input.json b/test/test_pyfans/input.json new file mode 100644 index 0000000..b73e52f --- /dev/null +++ b/test/test_pyfans/input.json @@ -0,0 +1,31 @@ +{ + "ms_filename": "../microstructures/sphere32.h5", + "ms_datasetname": "/sphere/32x32x32/ms", + "ms_L": [1.0, 1.0, 1.0], + + "problem_type": "mechanical", + "matmodel": "LinearElasticIsotropic", + "material_properties":{ + "bulk_modulus": [62.5000, 222.222], + "shear_modulus": [28.8462, 166.6667] + }, + + "method": "cg", + "error_parameters":{ + "measure": "Linfinity", + "type": "absolute", + "tolerance": 1e-10 + }, + "n_it": 100, + "macroscale_loading": [ + [[1, 0, 0, 0, 0, 0]], + [[0, 1, 0, 0, 0, 0]], + [[0, 0, 1, 0, 0, 0]], + [[0, 0, 0, 1, 0, 0]], + [[0, 0, 0, 0, 1, 0]], + [[0, 0, 0, 0, 0, 1]] + ], + + "results": ["stress_average", "strain_average", "absolute_error", "phase_stress_average", "phase_strain_average", + "microstructure", "displacement", "stress", "strain"] +} diff --git a/test/test_pyfans/micro-manager-config-mech.json b/test/test_pyfans/micro-manager-config-mech.json deleted file mode 100644 index 14886e6..0000000 --- a/test/test_pyfans/micro-manager-config-mech.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "micro_file_name": "MicroFANS", - "coupling_params": { - "config_file_name": "../../precice-config.xml", - "macro_mesh_name": "dummy-mesh", - "read_data_names": {"strains1to3": "vector", "strains4to6": "vector"}, - "write_data_names": {"stresses1to3": "vector", "stresses4to6": "vector"} - }, - "simulation_params": { - "macro_domain_bounds": [-0.9144, 0.9144, -0.4572, 0.4572, 0.0, 0.73152], - "micro_dt": 0.5 - } -} diff --git a/test/test_pyfans/micro_mech.py b/test/test_pyfans/run_fans_as_library.py similarity index 100% rename from test/test_pyfans/micro_mech.py rename to test/test_pyfans/run_fans_as_library.py