Package: grpc4bmi
grpc4bmiPurposeThis software allows you to wrap yourBasic Model Interface (BMI)implementation in a server process and communicate with it via the included Python client. The communication is serialized to protocol buffers byGRPCand occurs over network ports. Can run models in isolated containers using Docker or Apptainer.InstallationOptionally, create your virtual environment and activate it, Then, runpipinstallgrpc4bmion the client (Python) side. If your server model is implemented in Python, do the same in the server environment (e.g. docker container). If the model is implemented in R, run insteadpipinstallgrpc4bmi[R]If the model is implemented in Julia, run insteadpipinstallgrpc4bmi[julia]in the server environment. For bleeding edge version from GitHub usepipinstallgit+https://github.com/eWaterCycle/grpc4bmi.git#egg=grpc4bmiFinally if the model is implemented in C or C++, clone this git repo and runmake
makeinstallin the cpp folder.UsageModel written in PythonA model should be a subclass of theBmiclass from thebmipypackage.For inspiration look at theexamplein the test directory.To start a server process that allows calls to your BMI implementation, typerun-bmi-server--name<PACKAGE>.<MODULE>.<CLASS>--port<PORT>--path<PATH>where<PACKAGE>, <MODULE>are the python package and module containing your implementation,<CLASS>is your
bmi model class name,<PORT>is any available port on the host system, and optionally<PATH>denotes an
additional path that should be added to the system path to make your implementation work. The name option above is
optional, and if not provided the script will look at the environment variablesBMI_PACKAGE,BMI_MODULEandBMI_CLASS. Similarly, the port can be defined by the environment variableBMI_PORT.
This software assumes that your implementation constructor has no parameters.Model written in C/C++ (beta)Create an executable along the lines of cpp/run-bmi-server.cc. You can copy the file and replace the functionBmi*create_model_instance(){/* Return your new BMI instance pointer here... */}with the instantiation of your model BMI. The model needs to implement the csdms BMI for C, but you may also implement our more object-oriented C++ interfaceBmiCppExtension.Model written in RThe grpc4bmi Python package can also run BMI models written in R if the model is a subclass ofAbstractBmiSeehttps://github.com/eWaterCycle/bmi-rfor instruction on R and Docker.Run the R model a server withrun-bmi-server--langR[--path<RfilewithBMImodel>]--name[<PACKAGE>::]<CLASS>--port<PORT>For example withWALRUSuserun-bmi-server--langR--path~/git/eWaterCycle/grpc4bmi-examples/walrus/walrus-bmi.r--nameWalrusBmi--port55555Models written in JuliaThe grpc4bmi Python package can also run BMI models written in Julia if the model has an implementation of theBasicModelInterface.jl.Run the Julia model in Python withfromgrpc4bmi.bmi_julia_modelimportBmiJuliamymodel=BmiJulia.from_name('<package>.<model>','BasicModelInterface')For example withWflow.jluse# Install Wflow.jl package in the Julia environment managed by the juliacall Python package.fromjuliacallimportMainasjl
jl.Pkg.add("Wflow")# Create the modelfromgrpc4bmi.bmi_julia_modelimportBmiJuliamymodel=BmiJulia.from_name('Wflow.Model','Wflow.bmi.BMI')A Julia model has to be run locally. It can not be run in the default gRPC client/server Docker container mode because:Julia has no gRPC server implementationCalling Julia methods from Python gRPC server causes 100% CPU usage and no progressCalling Julia methods from C++ gRPC server causes segmentation faultsThe client sideThe client side has only a Python implementation. The default BMI client assumes a running server process on a given port.fromgrpc4bmi.bmi_grpc_clientimportBmiClientimportgrpcmymodel=BmiClient(grpc.insecure_channel("localhost:<PORT>"))printmymodel.get_component_name()mymodel.initialize(<FILEPATH>)...furtherBMIcalls...The package contains also client implementation that own the server process, either as a Python subprocess or a Docker
container or a Singularity container or a Apptainer container running therun-bmi-serverscript. For instancefromgrpc4bmi.bmi_client_subprocimportBmiClientSubProcessmymodel=BmiClientSubProcess(<PACKAGE>.<MODULE>.<CLASS>)will automatically launch the server in a sub-process andfromgrpc4bmi.bmi_client_dockerimportBmiClientDockermymodel=BmiClientDocker(<IMAGE>,<WORKDIRTOMOUNT>,input_dirs=[<INPUTDIRECTORIESTOMOUNT>])will launch a Docker container based on supplied Docker image
and will mount supplied directories to share files between the container and host.fromgrpc4bmi.bmi_client_singularityimportBmiClientSingularitymymodel=BmiClientSingularity(<IMAGE>,<WORKDIRTOMOUNT>,input_dirs=[<INPUTDIRECTORIESTOMOUNT>])will launch a singularity container on based supplied Singularity image
and will mount supplied directories to share files between the container and host.fromgrpc4bmi.bmi_client_apptainerimportBmiClientApptainermymodel=BmiClientApptainer(<IMAGE>,<WORKDIRTOMOUNT>,input_dirs=[<INPUTDIRECTORIESTOMOUNT>])will launch a Apptainer container on based supplied Apptainer image
and will mount supplied directories to share files between the container and host.For more documentation seehttps://grpc4bmi.readthedocs.io/.Development: generating the gRPC codeWhen developers change the proto-file, it is necessary to install gRPC tools Python packages in your Python environment:# Create virtual envpython3-mvenv.venv
.venv/bin/activate# Make sure latest pip and wheel are installpipinstall-Upipwheel
pipinstall-rdev-requirements.txt# For R integration also install the R extras withpipinstall-e.[R]# For building docs (cd docs && make html) also install the docs extras withpipinstall-e.[docs]and install the C++ runtime andprotoccommand as described inhttps://github.com/google/protobuf/blob/master/src/README.md.
After this, simply executing theproto_gen.shscript should do the job.