User Model Compilation Details

Description

  • This will describe the steps taken in the Continuity code that are required to go from a sympy user generated model to a compiled binary.
  • Each model type (e.g., Electrophysiology, Biomechanics, etc), extend the client/forms/ModelsForm class on the client side, which handles the model editor, and the server/utils/BuildSytem class on the server side, which handles compiling the model

  • The View Code, which displays the generated C/C++ code, option on the Compile tab is handled by ModelsForm.doGenerate, which calls the server command to generate the C/C++ code: (self.serverCmd(self.cmdPrefix + "generateCode", [codeType])

Electrophysiology

Code Generation

  • The EP model editor is in client/forms/IonicModelsForm.

  • When hitting the 'Compile' button, ModelsForm.saveOrCompileOnServer is called.

  • The sympy code is generated next by IonicModelsForm.generateCode which calls client/forms/EPSympyGenerator. generateCode returns the sympy generated code as a string.

  • ModelsForm.saveOrCompileOnServer then calls the server at: server/utils/IonicBuildSympy.saveAndCompile (which is in BuildSystem.py)

  • IonicBuildSympy.saveAndCompile will save the sympy code to the server in a file named justmodel.py.

  • IonicBuildSympy.rawCompile will handle the sympy to C conversion and will call Instant to compile the model as follows:

    • rawCompile will call buildAndShow.py, which in-turn, calls gen_sympy_model.py which will generate the C code version of the sympy model, and will create files named: ode_model_model.cu and ode_model_model_pert_delta.c.

    • ode_model_model.cu contains function 'f' and ode_model_model_pert_delta.c contains functions 'advance_bes' and 'advance_be1', which is called by advance_bes.
    • buildAndShow will then call tweak_delta.py which will read in the ode_model_model_pert_delta.c file and create the final version of the model, named either: ode_model_model_pert_delta_tweak_cpu.c or ode_model_model_pert_delta_tweak.c if we are using the CPU or GPU, respectively.

  • Finally, Instant will read in the source from src/ode_cuda/ode_solver_cpu.c and compile that file. The previously generated files (ode_model_model.cu and ode_model_model_pert_delta_tweak_cpu.c) are included in ode_solver_cpu.c via the #include select_cell_model.h directive.

  • buildAndShow.py and gen_sympy_model.py are located in src/ode_cuda, but during compilation are copied to the directory where the binary get created.

Solving a Problem

  • Solving starts in server/problem/Electrophysiology.py

Biomechanics Dynamic + Constitutive Model

Code Generation

  • Currently, if you compile a dynamic model from the Dynamic Model Editor (starting from ActiveTensionModelsForm.py), it follows a different route than if you compile it in conjunction with a constitutive model.

  • The steps below outline the scenario when compiling a constitutive model that has a dynamic model associated with it.
  • The compile button is linked to EquationsEditorNew.doCompile(), which calls ModelsForm.saveAndCompile, which calls ModelsForm.saveOrCompileOnServer, which calls generateCode

  • GenerateCode is subclassed in MatModelsForm.

  • MatModelsForm.generateCode will then call src/csrc/strain_energy/sympy_to_c.parse_table_file, which will parse all the equations and extract all the different variable types used in the equations.

  • If sympy_to_c.parse_table_file finds a variable type of 'dynamic_var', that will let the code generator know that it will also have to deal with a dynamic model, and will then call biomechanicsCommands.GenDynamics.

  • GenDynamics will generate the sympy code from the currently submitted dynamic model (stored_data.activeTensionEquations), by calling client/forms/EPSympyGenerator, which actually does the code generation.

  • GenDynamics will then call IonicBuildSympy.rawCompileDynamics

  • IonicBuildSympy.rawCompileDynamics will:

    • Write the generated sympy code to justmodel.py
    • Generate dynamicData.pickle
    • Generate ode_model_model_pert_delta_tweak_cpu_mech.c
    • Generate odecusingle.so.
  • dynamicData.pickle contains the state variables and the dynamic equation, which the constitutive model needs to know about. For example, for the Hilltype model, the dynamicData.pickle file contains:

    [['Lsi', 'Con'], {'T_active': '    T_active = rpar_global[16]*y_global[0]*max(-0.01, (rpar_global[2] - y_global[1])/rpar_global[12])*max(y_global[1] - rpar_global[5], 0.0001);'}]
    
  • ode_model_model_pert_delta_tweak_cpu_mech.c contains the dynamic code that needs to be included with the constitutive model when it is compiled.

  • Now that the dynamic model has been compile, the code continues on in MatModelsForm.generateCode and will call sympy_to_c.generate_c

  • sympy_to_c.generate_c will generate the C code that gets compiled in src/csrc/strain_energy/strain_energy.cpp. During the code generation process, the code will look for the presence of the ode_model_model_pert_delta_tweak_cpu_mech.c file, and will include that into strain_energy.cpp if it is found.

  • Additionally, during the code gen process, if an equation is of the form "dynamicVar()", it will then look for the dynamicData.pickle file and put that equation into strain_energy.cpp

  • Once all the code generation is completed, ModelsForm.saveOrCompileOnServer will call ConstitutiveBuildSympy.saveAndCompile, and eventually the final compilation will occur at ConstitutiveBuildSympy.rawCompile.

  • The dynamic binary is created in src/ode_cuda, but will be copied to pcty/server/problem/Biomechanics/ActiveTensionModels/<modelName>

  • The constitutive binary is created in src/csrc/strain_energy and will be copied to pcty/server/problem/Biomechanics/ and will be renamed to constitutive model name.