shimwell / openmc-online-demo

An online Jupyter deployment of OpenMC
Other
4 stars 0 forks source link

adding openmc wasm executable #1

Open shimwell opened 1 year ago

shimwell commented 1 year ago

ideally we would have the openmc executable compiled to web assembly

I tried with this docker container

FROM emscripten/emsdk:3.1.48

RUN git clone --recurse-submodules https://github.com/openmc-dev/openmc.git

RUN mkdir openmc/build

RUN apt-get update -y
RUN apt install g++ cmake libhdf5-dev libpng-dev -y

build and run with these commands

docker build  -t openmc_wasm .
docker run -it --entrypoint "/bin/bash" openmc_wasm

from within the docker command promt follow instructions here https://gist.github.com/WesThorburn/00c47b267a0e8c8431e06b14997778e4

cd openmc
CMAKE_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
cd build
emcmake cmake ..
make -j

this errors with the following message

[100%] Linking CXX executable ../../bin/test_tally.js
wasm-ld: error: unable to find library -lhdf5
wasm-ld: error: unable to find library -lcrypto
wasm-ld: error: unable to find library -lcurl
wasm-ld: error: unable to find library -lsz
wasm-ld: error: unable to find library -lz
wasm-ld: error: unable to find library -lhdf5_hl
em++: error: '/emsdk/upstream/bin/wasm-ld -o ../../bin/test_tally.wasm CMakeFiles/test_tally.dir/test_tally.cpp.o ../../lib/libCatch2Main.a ../../lib/libopenmc.a ../../lib/libCatch2.a -lhdf5 -lcrypto -lcurl -lsz -lz -lhdf5_hl ../../lib/libfmt.a ../../lib/libpugixml.a -L/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten -lGL -lal -lhtml5 -lstubs -lnoexit -lc -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr /tmp/tmpgwon8u8_libemscripten_js_symbols.so --export-if-defined=main --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=__main_argc_argv --export=stackSave --export=stackRestore --export=stackAlloc --export=__errno_location --export=__get_temp_ret --export=__set_temp_ret --export=__wasm_call_ctors --export-table -z stack-size=65536 --initial-memory=16777216 --max-memory=16777216 --no-entry --table-base=1 --global-base=1024' failed (returned 1)
make[2]: *** [tests/cpp_unit_tests/CMakeFiles/test_tally.dir/build.make:105: bin/test_tally.js] Error 1
make[1]: *** [CMakeFiles/Makefile2:1266: tests/cpp_unit_tests/CMakeFiles/test_tally.dir/all] Error 2
make: *** [Makefile:146: all] Error 2
shimwell commented 1 year ago

Looks like libraries need to be built and linked https://emscripten.org/docs/compiling/Building-Projects.html#using-libraries

shimwell commented 1 year ago

Perhaps add hdf5 with this repo https://github.com/usnistgov/libhdf5-wasm

bilal-07 commented 1 year ago

I download the hdf5 library from this URL: and install the library in Dockerfile. Below is the complete Dockerfile.

FROM emscripten/emsdk:3.1.48

WORKDIR /app

**# Install dependencies**
RUN apt-get update -y && apt-get install build-essential g++ cmake libhdf5-dev libpng-dev mpich libmpich-dev libhdf5-serial-dev libhdf5-mpich-dev -y

**# Download and build HDF5**
RUN wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.3/src/hdf5-1.12.3.tar.gz
RUN tar -xzvf hdf5-1.12.3.tar.gz
WORKDIR hdf5-1.12.3
RUN ./configure --prefix=/emsdk/upstream/emscripten/system/include/hdf5 --disable-shared
RUN make
RUN make install

WORKDIR /app
RUN git clone --recurse-submodules https://github.com/openmc-dev/openmc.git
WORKDIR /app/openmc/build

RUN emcmake cmake ..

RUN make -j
bilal-07 commented 1 year ago

I found the hdf5 library binaries in this path and exported the path in the Dockerfile but still I face the missing library issues:

ENV HDF5_LIB_PATH /usr/lib/x86_64-linux-gnu/

RUN ln -s /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5.a /usr/bin/libhdf5.a

ENV LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/hdf5/serial:$LD_LIBRARY_PATH

bilal-07 commented 1 year ago

After that, I used this GitHub repo https://github.com/usnistgov/libhdf5-wasm.git to install the hdf5 library but still faced a missing library issue. Commands that I run in the Dockerfile. This hdf5 library needs a cmake version greater or equal to 3.24.

RUN wget https://github.com/Kitware/CMake/releases/download/v3.28.0-rc4/cmake-3.28.0-rc4.tar.gz \
&& tar -zxvf cmake-3.28.0-rc4.tar.gz \
&& cd cmake-3.28.0-rc4 \
&& ./bootstrap \
&& make \
&& make install

# Clone the libhdf5-wasm repository
RUN git clone --recurse-submodules https://github.com/usnistgov/libhdf5-wasm.git
WORKDIR libhdf5-wasm
RUN make
shimwell commented 1 year ago

Thanks for your efforts,

I've tried adding some lines to the openmc CMakeLists.txt file so that it fetches the libhdf5-wasm as suggested in the https://github.com/usnistgov/libhdf5-wasm readme file

I added these lines and saved a new CMakelists.txt locally

include(FetchContent)

project(libhdf5-test
    VERSION 1.0.0
    DESCRIPTION "test the availability of libhdf5"
    LANGUAGES CXX C
)

FetchContent_Declare(
  libhdf5-wasm
  URL https://github.com/usnistgov/libhdf5-wasm/releases/download/v0.4.2_3.1.43/HDF5-1.14.2-Emscripten.tar.gz
)
FetchContent_MakeAvailable(libhdf5-wasm)
set(HDF5_DIR ${libhdf5-wasm_SOURCE_DIR}/cmake)
find_package(HDF5 REQUIRED CONFIG)

CMakeLists.txt

but this also appeared to not work as I still got the same missing libraries on the error message

The dockerfile has a few more lines in it and now looks like this

FROM emscripten/emsdk:3.1.43
# using 3.1.43 to match release of libhdf5-wasm which is available for 3.1.43 and older
# FROM emscripten/emsdk:3.1.48

RUN git clone --recurse-submodules https://github.com/openmc-dev/openmc.git

RUN mkdir openmc/build

RUN apt-get update -y
RUN apt install g++ cmake libhdf5-dev libpng-dev -y

# modified version of the openmc cmakelists file with a fetch for libhdf5-wasm
COPY CMakeLists.txt openmc
RUN cd openmc/ \
    && CMAKE_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
RUN cd openmc/build \
    && emcmake cmake ..
RUN cd openmc/build \
    && make -j
shimwell commented 1 year ago

not sure but perhaps the cmakelists file needs another few changes

target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES}
                      xtensor gsl::gsl-lite-v1 fmt::fmt)

to

target_link_libraries(libopenmc ${ldflags} hdf5_hl_cpp-static hdf5_cpp-static
                      xtensor gsl::gsl-lite-v1 fmt::fmt)
bilal-07 commented 1 year ago

I resolve these three missing library issues:

    • wasm-ld: error: unable to find library -lcrypto
  1. wasm-ld: error: unable to find library -lcurl
  2. wasm-ld: error: unable to find library -lsz

    using the below commands: RUN emcmake cmake -DHDF5_ROOT=/emsdk/upstream/emscripten/system/include/hdf5/bin ..

shimwell commented 1 year ago

many thanks @bilal-07 are you able to provide the full dockerfile for that :pray:

bilal-07 commented 1 year ago

Here is the complete Dockerfile. @shimwell

FROM emscripten/emsdk:3.1.48

# Set the working directory
WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake libhdf5-dev libpng-dev mpich libmpich-dev libhdf5-serial-dev libhdf5-mpich-dev

# Download and build HDF5
RUN wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.3/src/hdf5-1.12.3.tar.gz && \
    tar -xzvf hdf5-1.12.3.tar.gz && \
    cd hdf5-1.12.3 && \
    ./configure --prefix=/emsdk/upstream/emscripten/system/include/hdf5 && \
    make && \
    make install

# Clone your repository
WORKDIR /app
RUN git clone --recurse-submodules https://github.com/openmc-dev/openmc.git

# Create build directory
WORKDIR /app/openmc/build

RUN find / -name libhdf5.a
# Configure the build with emcmake
RUN emcmake cmake -DHDF5_ROOT=/emsdk/upstream/emscripten/system/include/hdf5/bin ..
RUN make -j VERBOSE=1
shimwell commented 1 year ago

Thanks for the dockerfile, I built it and see that it has less missing libraries :tada: previously

wasm-ld: error: unable to find library -lhdf5
wasm-ld: error: unable to find library -lcrypto
wasm-ld: error: unable to find library -lcurl
wasm-ld: error: unable to find library -lsz
wasm-ld: error: unable to find library -lz
wasm-ld: error: unable to find library -lhdf5_hl

now

wasm-ld: error: unable to find library -lhdf5
wasm-ld: error: unable to find library -lz
wasm-ld: error: unable to find library -lhdf5_hl

many thanks

shimwell commented 1 year ago

I've tried to add zlib (called lz in error message) by downloading the release and building it with emake make.

The libz.a file can be found with the find command just like libhdf5.a and libhdf5_hl.a

Then I've tried adding a DZLIB_INCLUDE_DIR command on the cmake command but it doesn't appear to help with the error messages which are still

wasm-ld: error: unable to find library -lhdf5
wasm-ld: error: unable to find library -lz
wasm-ld: error: unable to find library -lhdf5_hl

So I don't think cmake is finding the .a files

Here is the latest dockerfile

FROM emscripten/emsdk:3.1.48

# Set the working directory
WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake libhdf5-dev libpng-dev mpich libmpich-dev libhdf5-serial-dev libhdf5-mpich-dev

# Download and build HDF5
RUN wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.3/src/hdf5-1.12.3.tar.gz && \
    tar -xzvf hdf5-1.12.3.tar.gz && \
    cd hdf5-1.12.3 && \
    ./configure --prefix=/emsdk/upstream/emscripten/system/include/hdf5 && \
    make -j && \
    make install

RUN wget https://github.com/madler/zlib/releases/download/v1.3/zlib-1.3.tar.gz && \
    tar -xzvf zlib-1.3.tar.gz && \
    cd zlib-1.3 && \
    emconfigure ./configure --prefix=/emsdk/upstream/emscripten/system/include/zlib && \
    emmake make -j && \
    emmake make install

# Clone your repository
WORKDIR /app
RUN git clone --recurse-submodules https://github.com/openmc-dev/openmc.git

# Create build directory
WORKDIR /app/openmc/build

RUN find / -name libhdf5.a
RUN find / -name libhdf5_hl.a
RUN find / -name libz.a

# Configure the build with emcmake
RUN emcmake cmake -DHDF5_ROOT=/emsdk/upstream/emscripten/system/include/hdf5/bin -DZLIB_INCLUDE_DIR=/emsdk/upstream/emscripten/system/include/zlib/lib ..
RUN make -j VERBOSE=1
shimwell commented 1 year ago

I've been trying embuilder build and have reduced the missing libraries to just 2 now. So I suspect hdf5 is not being found when compiling, unfortunatly embuilder does not include hdf5

wasm-ld: error: unable to find library -lhdf5
wasm-ld: error: unable to find library -lhdf5_hl

here is the dockerfile

FROM emscripten/emsdk:3.1.48

# Set the working directory
WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake libhdf5-dev libpng-dev mpich libmpich-dev libhdf5-serial-dev libhdf5-mpich-dev

# Download and build HDF5
RUN wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.3/src/hdf5-1.12.3.tar.gz && \
    tar -xzvf hdf5-1.12.3.tar.gz && \
    cd hdf5-1.12.3 && \
    ./configure --prefix=/emsdk/upstream/emscripten/system/include/hdf5 && \
    make -j && \
    make install

# Clone your repository
WORKDIR /app
RUN git clone --recurse-submodules https://github.com/openmc-dev/openmc.git

# Create build directory
WORKDIR /app/openmc/build

RUN embuilder build zlib
RUN embuilder build libpng

RUN find / -name libhdf5.a
RUN find / -name libhdf5_hl.a
RUN find / -name libz.a

# Configure the build with emcmake
RUN emcmake cmake -DHDF5_ROOT=/emsdk/upstream/emscripten/system/include/hdf5/bin ..
RUN make -j VERBOSE=1
shimwell commented 12 months ago

updated the docker image to emsdk 3.1.49 but there error persist

# docker build -t openmc_wasm

FROM emscripten/emsdk:3.1.49

# Set the working directory
WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake libhdf5-dev libpng-dev mpich libmpich-dev libhdf5-serial-dev libhdf5-mpich-dev

# Download and build HDF5
RUN wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.3/src/hdf5-1.12.3.tar.gz && \
    tar -xzvf hdf5-1.12.3.tar.gz && \
    cd hdf5-1.12.3 && \
    ./configure --prefix=/emsdk/upstream/emscripten/system/include/hdf5 && \
    make -j && \
    make install

# Clone your repository
WORKDIR /app
RUN git clone --recurse-submodules https://github.com/openmc-dev/openmc.git

# Create build directory
WORKDIR /app/openmc/build

RUN embuilder build zlib
RUN embuilder build libpng

RUN find / -name libhdf5.a
RUN find / -name libhdf5_hl.a
RUN find / -name libz.a

# Configure the build with emcmake
RUN emcmake cmake -DHDF5_ROOT=/emsdk/upstream/emscripten/system/include/hdf5/bin ..
RUN make -j VERBOSE=1
shimwell commented 12 months ago

removed x86 packages and downloading a prebuilt hdf5 wasm

error is now

wasm-ld: error: /emsdk/upstream/emscripten/cache/sysroot/lib/libhdf5.a(H5Z.c.o): undefined symbol: SZ_encoder_enabled
wasm-ld: error: /emsdk/upstream/emscripten/cache/sysroot/lib/libhdf5.a(H5Zszip.c.o): undefined symbol: SZ_BufftoBuffDecompress
wasm-ld: error: /emsdk/upstream/emscripten/cache/sysroot/lib/libhdf5.a(H5Zszip.c.o): undefined symbol: SZ_BufftoBuffCompress

docker file is now

# docker build -t openmc_wasm .
# docker run -it --entrypoint /bin/bash openmc_wasm

FROM emscripten/emsdk:3.1.49

WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake

# this doesn't appear to help avoid the missing lib error
# RUN embuilder build zlib
RUN embuilder build libpng

RUN git clone --depth 1 --recurse-submodules https://github.com/openmc-dev/openmc.git

RUN wget https://github.com/usnistgov/libhdf5-wasm/releases/download/v0.4.2_3.1.43/HDF5-1.14.2-Emscripten.tar.gz && \
    tar -f HDF5-1.14.2-Emscripten.tar.gz -z -C /emsdk/upstream/emscripten/cache/sysroot -x

# Create build directory
WORKDIR /app/openmc/build

# Configure the build with emcmake
RUN emcmake cmake -DLDFLAGS=-static -DHDF5_ROOT=/emsdk/upstream/emscripten/cache/sysroot ..
RUN emcmake cmake -DHDF5_ROOT=/emsdk/upstream/emscripten/cache/sysroot ..
RUN make -j VERBOSE=1
bmaranville commented 12 months ago

The libz.a and libsz.a libraries used in building libhdf5 are included in the download, next to libhdf5.a and libhdf5_hl.a in /lib They are not properly included in the list of link libraries after find_package(HDF5 REQUIRED CONFIG) though... I was able to build openmc like this (from the openmc repo root folder)

mkdir hdf5
tar -xzf HDF5-1.14.2-Emscripten.tar.gz -C hdf5
export HDF5_ROOT=$(readlink -f hdf5)

mkdir build
cd build
emcmake cmake \
  -DOPENMC_BUILD_TESTS=OFF \
  -DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=$HDF5_ROOT/include \
  -DHDF5_LIBRARIES="$HDF5_ROOT/lib/libhdf5.a;$HDF5_ROOT/lib/libz.a;$HDF5_ROOT/lib/libsz.a" \
  -DHDF5_HL_LIBRARIES="$HDF5_ROOT/lib/libhdf5_hl.a" \
  -DCMAKE_FIND_PACKAGE_PREFER_CONFIG=TRUE \
  -DHDF5_DIR="$HDF5_ROOT/cmake" \
  -DZLIB_LIBRARY="$HDF5_ROOT/lib/libz.a" \
  -DZLIB_INCLUDE_DIR="$HDF5_ROOT/include" \
  -DCMAKE_CXX_LINK_FLAGS="-sALLOW_MEMORY_GROWTH=1" \
  ..

emmake make -j 

Note that I disabled tests because I got a duplicate symbol error in test_interpolation.cpp:

wasm-ld: error: duplicate symbol: openmc::interpolate(gsl::span, gsl::span, double, openmc::Interpolation)

defined in CMakeFiles/test_interpolate.dir/test_interpolate.cpp.o defined in ../../lib/libopenmc.a(filter_energyfunc.cpp.o)

bmaranville commented 12 months ago

Also, the other tests work - if I comment out test_interpolate in tests/cpp_unit_tests/CMakeLists.txt, the other tests build and execute and pass:

> cd bin
> node test_distribution.js
Randomness seeded to: 1928082616
===============================================================================
All tests passed (14 assertions in 2 test cases)

> node test_tally.js
Randomness seeded to: 3656487369
===============================================================================
All tests passed (12 assertions in 1 test case)

> node test_file_utils.js
Randomness seeded to: 3256973951
===============================================================================
All tests passed (12 assertions in 3 test cases)
bmaranville commented 12 months ago

One more note - in your README that you mention that h5py is not available in Jupyterlite - this is not true for recent versions (h5py has been added to the base pyodide distribution, as well as newer Jupyterlite)

bmaranville commented 12 months ago

There is one more flag that is needed in order to make the executable openmc.js work - you have to enable memory growth. I have edited my comment above to include -sALLOW_MEMORY_GROWTH=1

For testing it with node, I also added -sNODERAWFS=1 -sFORCE_FILESYSTEM=1 Since it is hard to pass environment variables through to emscripten processes (but not impossible, see https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#environment-variables) I modified the materials.xml file in the test so that it included my local cross_sections.xml:

<?xml version="1.0"?>
<materials>
  <cross_sections>/home/bbm/nndc_hdf5/cross_sections.xml</cross_sections>
   ...
</materials>

After that, I can run the wasm executable with node:

> node openmc.js --geometry-debug ../../tests/regression_tests/density
                                %%%%%%%%%%%%%%%
                           %%%%%%%%%%%%%%%%%%%%%%%%
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                                    %%%%%%%%%%%%%%%%%%%%%%%%
                                     %%%%%%%%%%%%%%%%%%%%%%%%
                 ###############      %%%%%%%%%%%%%%%%%%%%%%%%
                ##################     %%%%%%%%%%%%%%%%%%%%%%%
                ###################     %%%%%%%%%%%%%%%%%%%%%%%
                ####################     %%%%%%%%%%%%%%%%%%%%%%
                #####################     %%%%%%%%%%%%%%%%%%%%%
                ######################     %%%%%%%%%%%%%%%%%%%%
                #######################     %%%%%%%%%%%%%%%%%%
                 #######################     %%%%%%%%%%%%%%%%%
                 ######################     %%%%%%%%%%%%%%%%%
                  ####################     %%%%%%%%%%%%%%%%%
                    #################     %%%%%%%%%%%%%%%%%
                     ###############     %%%%%%%%%%%%%%%%
                       ############     %%%%%%%%%%%%%%%
                          ########     %%%%%%%%%%%%%%
                                      %%%%%%%%%%%

                 | The OpenMC Monte Carlo Code
       Copyright | 2011-2023 MIT, UChicago Argonne LLC, and contributors
         License | https://docs.openmc.org/en/latest/license.html
         Version | 0.14.1-dev
        Git SHA1 | 9830efaf2aadf68ffde9a054388bacef20ab5645
       Date/Time | 2023-11-27 12:30:30

 Reading settings XML file...
 Reading cross sections XML file...
 Reading materials XML file...
 Reading geometry XML file...
 Reading U235 from /home/bbm/nndc_hdf5/U235.h5
 Reading U238 from /home/bbm/nndc_hdf5/U238.h5
 Reading H1 from /home/bbm/nndc_hdf5/H1.h5
 Minimum neutron data temperature: 294 K
 Maximum neutron data temperature: 294 K
 Preparing distributed cell instances...
 Reading plot XML file...
 Writing summary.h5 file...
 WARNING: Cell overlap checking is ON.
 Maximum neutron transport energy: 20000000 eV for U235
 Initializing source particles...

 ====================>     K EIGENVALUE SIMULATION     <====================

  Bat./Gen.      k            Average k
  =========   ========   ====================
        1/1    1.20883
        2/1    1.10631
        3/1    1.12003
        4/1    1.12568
        5/1    1.07936
        6/1    1.14136
        7/1    1.10553    1.12344 +/- 0.01791
        8/1    1.11293    1.11994 +/- 0.01092
        9/1    1.07564    1.10887 +/- 0.01350
       10/1    1.05217    1.09753 +/- 0.01543
 Creating state point statepoint.10.h5...

 =======================>     TIMING STATISTICS     <=======================

 Total time for initialization     = 2.5344e-01 seconds
   Reading cross sections          = 1.9321e-01 seconds
 Total time in simulation          = 7.3894e-02 seconds
   Time in transport only          = 6.7888e-02 seconds
   Time in inactive batches        = 3.9527e-02 seconds
   Time in active batches          = 3.4367e-02 seconds
   Time synchronizing fission bank = 1.2590e-03 seconds
     Sampling source sites         = 1.1632e-03 seconds
     SEND/RECV source sites        = 6.8888e-05 seconds
   Time accumulating tallies       = 2.9593e-05 seconds
   Time writing statepoints        = 3.7460e-03 seconds
 Total time for finalization       = 1.1320e-06 seconds
 Total time elapsed                = 3.3428e-01 seconds
 Calculation Rate (inactive)       = 126496 particles/second
 Calculation Rate (active)         = 145487 particles/second

 ============================>     RESULTS     <============================

 k-effective (Collision)     = 1.09897 +/- 0.01112
 k-effective (Track-length)  = 1.09753 +/- 0.01543
 k-effective (Absorption)    = 1.10874 +/- 0.00713
 Combined k-effective        = 1.11006 +/- 0.01303
 Leakage Fraction            = 0.52180 +/- 0.00399

 ==================>     CELL OVERLAP CHECK SUMMARY     <===================

 Cell ID      No. Overlap Checks
        1              9461
        2             17234
        3             16477
        4             10603

 There were 0 cells with less than 10 overlap checks

Note that this binary is now portable to any platform! openmc.zip

shimwell commented 12 months ago

Wow thank you so much for looking into this. This is really going to change everything for us over in opemc world from our tutorial hosting to our porting to windows.

I would have never figured out these tricky aspects of the code especially those extra flags.

The only thing that confuses me a little is the h5py as I was trying to add it to over here to get it working with xeus-python + JupyterLite as I thought that was the only way. I'm going to look into how h5py was added to pyodide distribution, as well as newer Jupyterlite and see if that helps get h5py working on working for xeus-python.

I'm going to tinker with everything, many many thanks

bmaranville commented 12 months ago

I helped with getting h5py added to pyodide, so let me know if there's anything I can do to help with your problem, as well.

shimwell commented 12 months ago

I'm seeing a couple of errors when running the latest docker file

first error is related to PNG

CMake Error in CMakeLists.txt:
#   Imported target "PNG::PNG" includes non-existent path

I'm not sure why as cmake reports libpng is found at /emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/libpng.a. However this can be avoided by modifying the CMakeLists.txt and commenting out lines 513 to 516

Next error is during the emmake make -j VERBOSE=1 command

#0 25.23 make  -f CMakeFiles/openmc.dir/build.make CMakeFiles/openmc.dir/build
#0 25.24 make[2]: Entering directory '/app/openmc/build'
#0 25.24 make[2]: *** No rule to make target '/lib/libhdf5.a', needed by 'bin/openmc.js'.  Stop.
#0 25.24 make[2]: *** Waiting for unfinished jobs....

Docker file and modified cmakelists.txt attached for reproduction

CMakeLists.txt

# docker build -t openmc_wasm .
# docker run -it --entrypoint /bin/bash openmc_wasm

FROM emscripten/emsdk:3.1.49

WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake

RUN embuilder build libpng

RUN git clone --depth 1 --recurse-submodules https://github.com/openmc-dev/openmc.git

RUN wget https://github.com/usnistgov/libhdf5-wasm/releases/download/v0.4.2_3.1.43/HDF5-1.14.2-Emscripten.tar.gz && \
    tar -f HDF5-1.14.2-Emscripten.tar.gz -z -C /emsdk/upstream/emscripten/cache/sysroot -x
RUN export HDF5_ROOT=/emsdk/upstream/emscripten/cache/sysroot/hdf5

WORKDIR /app/openmc
# this file has lines 513 to 516 commented out so PNG is not looked for
# COPY CMakeLists.txt .

# Create build directory
WORKDIR /app/openmc/build

# Configure the build with emcmake
RUN emcmake cmake \
  -DOPENMC_BUILD_TESTS=OFF \
  -DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=$HDF5_ROOT/include \
  -DHDF5_LIBRARIES="$HDF5_ROOT/lib/libhdf5.a;$HDF5_ROOT/lib/libz.a;$HDF5_ROOT/lib/libsz.a" \
  -DHDF5_HL_LIBRARIES="$HDF5_ROOT/lib/libhdf5_hl.a" \
  -DCMAKE_FIND_PACKAGE_PREFER_CONFIG=TRUE \
  -DHDF5_DIR="$HDF5_ROOT/cmake" \
  -DZLIB_LIBRARY="$HDF5_ROOT/lib/libz.a" \
  -DZLIB_INCLUDE_DIR="$HDF5_ROOT/include" \
  -DCMAKE_CXX_LINK_FLAGS="-sALLOW_MEMORY_GROWTH=1;-sNODERAWFS=1;-sFORCE_FILESYSTEM=1" \
  ..

RUN emmake make -j VERBOSE=1
bmaranville commented 12 months ago

Sorry - I was being clumsy stomping on the existing CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES... which was causing the PNG::PNG error I think (it was populating incorrects include dirs). It turns out it's not even needed.

Also, running "export HDF5_ROOT" in there was not properly setting the variable in the Dockerfile. Here is a modified Dockerfile that successfully builds openmc.js (including png support?)

# docker build -t openmc_wasm .
# docker run -it --entrypoint /bin/bash openmc_wasm

FROM emscripten/emsdk:3.1.49

WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake

RUN embuilder build libpng

RUN git clone --depth 1 --recurse-submodules https://github.com/openmc-dev/openmc.git

RUN wget https://github.com/usnistgov/libhdf5-wasm/releases/download/v0.4.2_3.1.43/HDF5-1.14.2-Emscripten.tar.gz && \
    tar -f HDF5-1.14.2-Emscripten.tar.gz -z -C /emsdk/upstream/emscripten/cache/sysroot -x
ARG HDF5_ROOT=/emsdk/upstream/emscripten/cache/sysroot

WORKDIR /app/openmc
# this file has lines 513 to 516 commented out so PNG is not looked for
# COPY CMakeLists.txt .

# Create build directory
WORKDIR /app/openmc/build

# Configure the build with emcmake
RUN emcmake cmake \
  -DOPENMC_BUILD_TESTS=OFF \
  -DHDF5_LIBRARIES="$HDF5_ROOT/lib/libhdf5.a;$HDF5_ROOT/lib/libz.a;$HDF5_ROOT/lib/libsz.a" \
  -DHDF5_HL_LIBRARIES="$HDF5_ROOT/lib/libhdf5_hl.a" \
  -DCMAKE_FIND_PACKAGE_PREFER_CONFIG=TRUE \
  -DHDF5_DIR="$HDF5_ROOT/cmake" \
  -DZLIB_LIBRARY="$HDF5_ROOT/lib/libz.a" \
  -DZLIB_INCLUDE_DIR="$HDF5_ROOT/include" \
  -DCMAKE_EXE_LINKER_FLAGS="-sALLOW_MEMORY_GROWTH=1 -sNODERAWFS=1 -sFORCE_FILESYSTEM=1" \
  ..

RUN emmake make -j VERBOSE=1
shimwell commented 11 months ago

The testing issue has been fixed over on the openmc repo so this docker should now work with -DOPENMC_BUILD_TESTS=ON \

... confirming the docker file now builds with tests on

shimwell commented 11 months ago

latest docker file

# docker build -t openmc_wasm .
# docker run -it --entrypoint /bin/bash openmc_wasm

FROM emscripten/emsdk:3.1.49

WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake

RUN embuilder build libpng
RUN git clone --depth 2 --recurse-submodules https://github.com/openmc-dev/openmc.git

RUN wget https://github.com/usnistgov/libhdf5-wasm/releases/download/v0.4.2_3.1.43/HDF5-1.14.2-Emscripten.tar.gz && \
    tar -f HDF5-1.14.2-Emscripten.tar.gz -z -C /emsdk/upstream/emscripten/cache/sysroot -x
ARG HDF5_ROOT=/emsdk/upstream/emscripten/cache/sysroot

WORKDIR /app/openmc

# Create build directory
WORKDIR /app/openmc/build

# Configure the build with emcmake
RUN emcmake cmake \
  -DOPENMC_BUILD_TESTS=ON \
  -DHDF5_LIBRARIES="$HDF5_ROOT/lib/libhdf5.a;$HDF5_ROOT/lib/libz.a;$HDF5_ROOT/lib/libsz.a" \
  -DHDF5_HL_LIBRARIES="$HDF5_ROOT/lib/libhdf5_hl.a" \
  -DCMAKE_FIND_PACKAGE_PREFER_CONFIG=TRUE \
  -DHDF5_DIR="$HDF5_ROOT/cmake" \
  -DZLIB_LIBRARY="$HDF5_ROOT/lib/libz.a" \
  -DZLIB_INCLUDE_DIR="$HDF5_ROOT/include" \
  -DCMAKE_EXE_LINKER_FLAGS="-sALLOW_MEMORY_GROWTH=1 -sNODERAWFS=1 -sFORCE_FILESYSTEM=1" \
  ..

RUN emmake make -j VERBOSE=1
shimwell commented 11 months ago

Next step is to run this openmc.js file through in this browser https://shimwell.github.io/openmc-online-demo/lab/index.html

bmaranville commented 11 months ago

Did you want to run it from a command-line in a terminal in the jupyterlite session?

shimwell commented 11 months ago

I've copied the files locally to my host (non docker) with these commands

id=$(docker create openmc_wasm)
docker cp $id:/app/openmc/build/bin/openmc.js .
docker cp $id:/app/openmc/build/bin/openmc.wasm .

I have also uploaded them to the repo here https://github.com/shimwell/openmc-online-demo/tree/main/content/bin

in the ideal world I would be able to run this openmc executable with the standard openmc python command model.run(). This method does accept an argument for the openmc_exec' which defaults to ='openmc'.

However I think that will need changes on the openmc side.

So running it from a command-line in a terminal in the jupyterlite session

I see you used node openmc.js to run it in the earlier comments so I shall give that a go first

shimwell commented 11 months ago

Unfortunately Screenshot from 2023-11-29 18-05-23

But I notice one can run javascript in jupyterlite with some magic command

%%js
alert("hello, world!");
bmaranville commented 11 months ago

If you want to use the python interface, I think it will be important to build libopenmc.so as a shared library so that python can call it with ctypes.CDLL("libopenmc.so"). This requires some different flags than when building an EXE (you can see some example shared library flags here: https://github.com/emscripten-forge/recipes/blob/c4727a8ee2e20eae562b2468cba21ef13d03e638/recipes/recipes_emscripten/python/adjust_sysconfig.py#L24

You also have to manually link in all the libraries, as CMake and. Emscripten do not currently have a built-in way to build shared libraries. Here is a Dockerfile that builds libopenmc.so in a way that it can be loaded from pyodide or the emscripten-forge python:

# docker build -t openmc_wasm .
# docker run -it --entrypoint /bin/bash openmc_wasm

FROM emscripten/emsdk:3.1.49

WORKDIR /app

# Install dependencies
RUN apt-get update -y && \
    apt-get install -y build-essential g++ cmake

RUN embuilder --pic build libpng
RUN git clone --depth 2 --recurse-submodules https://github.com/openmc-dev/openmc.git

RUN wget https://github.com/usnistgov/libhdf5-wasm/releases/download/v0.4.3_3.1.43/HDF5-1.14.2-Emscripten.tar.gz && \
    tar -f HDF5-1.14.2-Emscripten.tar.gz -z -C /emsdk/upstream/emscripten/cache/sysroot -x
ARG HDF5_ROOT=/emsdk/upstream/emscripten/cache/sysroot

WORKDIR /app/openmc

# Create build directory
WORKDIR /app/openmc/build

# Configure the build with emcmake
RUN emcmake cmake \
  -DOPENMC_BUILD_TESTS=OFF \
  -DHDF5_LIBRARIES="$HDF5_ROOT/lib/libhdf5.a;$HDF5_ROOT/lib/libz.a;$HDF5_ROOT/lib/libsz.a" \
  -DHDF5_HL_LIBRARIES="$HDF5_ROOT/lib/libhdf5_hl.a" \
  -DCMAKE_FIND_PACKAGE_PREFER_CONFIG=TRUE \
  -DHDF5_DIR="$HDF5_ROOT/cmake" \
  -DZLIB_LIBRARY="$HDF5_ROOT/lib/libz.a" \
  -DZLIB_INCLUDE_DIR="$HDF5_ROOT/include" \
  -DCMAKE_CXX_STANDARD=14 \
  ..

RUN emmake make -j VERBOSE=1 libopenmc
RUN emcc -sSIDE_MODULE=1 -sWASM_BIGINT \
   lib/libopenmc.a lib/libfmt.a lib/libpugixml.a \
   $HDF5_ROOT/lib/libhdf5.a \
   $HDF5_ROOT/lib/libz.a \
   $HDF5_ROOT/lib/libsz.a \
   $HDF5_ROOT/lib/wasm32-emscripten/pic/libpng.a \
   -o libopenmc.so

Notes

bmaranville commented 11 months ago

After you build the .so as above, you might want to embed it in the openmc WASM wheel file - for pyodide, this would involve

bmaranville commented 11 months ago

It might be tricky to get the python openmc code to be able to call the openmc executable from a javascript/webassembly environment. As far as I know os.system or subprocess don't work at all.

If you want to execute your code, it will probably have to be done by importing the main function from the openmc executable into the javascript environment where you're also running pyodid/xeus python. Then you can call main through the python->javascript api, e.g. "import js; js.openmc._main()". This is very different from how the executable is now called from python!

shimwell commented 11 months ago

Many thanks for all the pointers, I got the new dockerfile and built the libopenmc.so but that is as far as I got for now. Will keep going tomorrow

bmaranville commented 11 months ago

openmc-0.14.1.dev0-cp311-cp311-emscripten_3_1_45_wasm32.zip

This wheel should work for pyodide