Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Repository Guide

This repository contains the **Sibernetic** simulator along with Python
bindings and tests. The code base mixes C++ (in `src/` and `inc/`), OpenCL
kernels and a number of helper Python scripts.

## Layout
- `src/` – main C++ sources and OpenCL kernels (`sphFluid.cl`).
- `inc/` – C++ headers with physics constants, solver classes and helpers.
- `configuration/` – example configuration files for the simulator.
- `buffers/` – output data (created at runtime).
- `tests/` – Python tests; `run_all_tests.sh` wraps `sibernetic_c302.py`
for automated runs.
- Python utilities such as `main_sim.py`, `sibernetic_c302.py` and
`plot_positions.py` can drive the simulator or analyse its output.

## Building and Testing
To compile the C++ code use `make`. A convenience script `test.sh`
runs code formatting, static checks via **ruff**, builds the simulator
and executes the test suite:

```bash
./test.sh
```

`test.sh` in turn calls `run_all_tests.sh` which performs multiple
runs of `sibernetic_c302.py` and verifies the produced output files.

## Contributing Notes
- Keep C++ headers and sources under `inc/` and `src/` respectively.
- OpenCL kernels reside in `src/*.cl`.
- When adding Python scripts ensure they pass `ruff format` and
`ruff check`.
- Test additions should be placed under `tests/` and runnable via
`test.sh`.

19 changes: 15 additions & 4 deletions inc/owOpenCLSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
*******************************************************************************/

#define CL_TARGET_OPENCL_VERSION 120
#define CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY
#define CL_HPP_TARGET_OPENCL_VERSION 120
#define CL_HPP_MINIMUM_OPENCL_VERSION 120

#ifndef OW_OPENCL_SOLVER_H
#define OW_OPENCL_SOLVER_H
Expand All @@ -41,10 +44,16 @@
#endif

#if defined(__APPLE__) || defined(__MACOSX)
#include "../inc/OpenCL/cl.hpp"
// #include <OpenCL/cl_d3d10.h>
#include "OpenCL/cl.hpp"
//# include <OpenCL/cl_d3d10.h>
#else
#if __has_include(<CL/cl.hpp>)
#include <CL/cl.hpp>
#elif __has_include(<CL/opencl.hpp>)
#include <CL/opencl.hpp>
#else
#include "OpenCL/cl.hpp"
#endif
#endif

#include "owConfigProperty.h"
Expand Down Expand Up @@ -130,7 +139,9 @@ class owOpenCLSolver {
const int size);
void destroy() {
delete[] gridNextNonEmptyCellBuffer;
gridNextNonEmptyCellBuffer = nullptr;
delete[] _particleIndex;
_particleIndex = nullptr;
}
// Initialization of openCl data buffers
void initializeBuffers(const float *, const float *, owConfigProperty *,
Expand Down Expand Up @@ -207,8 +218,8 @@ class owOpenCLSolver {
cl::Kernel computeInteractionWithMembranes_finalize;

// Needed for sorting stuff
int *_particleIndex;
int *gridNextNonEmptyCellBuffer;
int *_particleIndex = nullptr;
int *gridNextNonEmptyCellBuffer = nullptr;
};

#endif // OW_OPENCL_SOLVER_H
4 changes: 3 additions & 1 deletion inc/owPhysicTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

#include "owPhysicsFluidSimulator.h"

void test_energy_conservation(int argc, char **argv);
// Run the energy conservation test for the specified number of iterations.
// If iterations <= 0 the default value inside the implementation is used.
void test_energy_conservation(int argc, char **argv, int iterations = 0);


#endif /* OWPHYSICTEST_H_ */
6 changes: 6 additions & 0 deletions main_sim.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
Utility module used by the C++ simulator to generate
synthetic muscle activation patterns. Can also be run
standalone to visualize these waves.
"""

import math
import sys

Expand Down
4 changes: 4 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ CXXFLAGS += $(shell $(PYTHON_CONFIG) --embed --cflags)
endif

CXXFLAGS += -fPIE
CXXFLAGS += -DCL_TARGET_OPENCL_VERSION=120 # Target OpenCL version is 1.2
CXXFLAGS += -DCL_HPP_TARGET_OPENCL_VERSION=120 # C++ bindings target OpenCL version 1.2
CXXFLAGS += -DCL_HPP_MINIMUM_OPENCL_VERSION=120 # Minimum OpenCL version supported is 1.2
CXXFLAGS += -DCL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY # Enable compatibility for program construction from arrays
EXTRA_LIBS := -L/usr/lib64/OpenCL/vendors/amd/ -L/opt/AMDAPP/lib/x86_64/ -L/usr/lib/x86_64-linux-gnu/

all: CXXFLAGS += -O3
Expand Down
6 changes: 6 additions & 0 deletions plot_positions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
Helper script to visualise particle positions and muscle
activations logged by the simulator. Used by `sibernetic_c302.py`
but can be invoked directly.
"""

import sys


Expand Down
18 changes: 13 additions & 5 deletions run_all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@
# files produced
set -ex

# Ensure system site-packages are visible to embedded Python
export PYTHONPATH="${PYTHONPATH:+$PYTHONPATH:}/usr/local/lib/python3.12/dist-packages:$(pwd)"
export PATH="/usr/bin:$PATH"

# No c302
python3 sibernetic_c302.py -test -noc302 -duration 0.1

python3 sibernetic_c302.py -test -noc302 -duration 0.054 -logstep 3

# c302
python3 sibernetic_c302.py -test -duration 1.1 -c302params C1
if command -v nrnivmodl >/dev/null 2>&1; then
python3 sibernetic_c302.py -test -duration 1.1 -c302params C1

# c302 + half_resolution
python3 sibernetic_c302.py -test -duration 1 -c302params C0 -configuration worm_alone_half_resolution
# c302 + half_resolution
python3 sibernetic_c302.py -test -duration 1 -c302params C0 -configuration worm_alone_half_resolution

# c302 + TestMuscle
python3 sibernetic_c302.py -test -duration 20 -c302params C0 -reference TargetMuscle -configuration worm_alone_half_resolution -logstep 500
# c302 + TestMuscle
python3 sibernetic_c302.py -test -duration 20 -c302params C0 -reference TargetMuscle -configuration worm_alone_half_resolution -logstep 500
else
echo "Skipping c302 tests due to missing NEURON" >&2
fi


41 changes: 25 additions & 16 deletions sibernetic_c302.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
from pyneuroml import pynml
"""
Entry point for running the Sibernetic simulator alongside
c302 neuronal models. Provides command line options for configuring
duration, device selection and other parameters.
"""

try:
from pyneuroml import pynml
except ImportError: # pyneuroml may not be installed for simple tests
pynml = None
import argparse
import re
import os
Expand Down Expand Up @@ -249,18 +258,19 @@ def dynamic_import(abs_module_path, class_name):


def run(a=None, **kwargs):
try:
import neuroml # noqa: F401
import pyneuroml # noqa: F401
import xlrd # noqa: F401
except Exception as e:
print_(
"Cannot import one of the required packages. Please install!\n"
"Exception: %s\n" % e
)

a = build_namespace(a, **kwargs)

if not a.noc302:
try:
import neuroml # noqa: F401
import pyneuroml # noqa: F401
import xlrd # noqa: F401
except Exception as e:
print_(
"Cannot import one of the required packages. Please install!\n"
"Exception: %s\n" % e
)

if not a.noc302:
try:
if "C302_HOME" in os.environ:
Expand Down Expand Up @@ -298,7 +308,7 @@ def run(a=None, **kwargs):
# sim_dir = "simulations/%s" % (sim_ref)
sim_dir = os.path.join(a.out_dir, sim_ref)

os.mkdir(sim_dir)
os.makedirs(sim_dir, exist_ok=True)

run_dir = "."
if "SIBERNETIC_HOME" in os.environ:
Expand Down Expand Up @@ -389,15 +399,14 @@ def run(a=None, **kwargs):
)

env = {
"DISPLAY": os.environ.get("DISPLAY")
if os.environ.get("DISPLAY") is not None
else "",
"DISPLAY": os.environ.get("DISPLAY") if os.environ.get("DISPLAY") else "",
"XAUTHORITY": os.environ.get("XAUTHORITY")
if os.environ.get("XAUTHORITY") is not None
if os.environ.get("XAUTHORITY")
else "",
"PYTHONPATH": ".:%s:%s"
% (os.environ.get("PYTHONPATH", "."), os.path.abspath(sim_dir)),
"NEURON_MODULE_OPTIONS": "-nogui",
"PATH": os.environ.get("PATH", "/usr/bin"),
}

sim_start = time.time()
Expand Down
8 changes: 7 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ bool skip_display_particles = false;
bool skip_display_membranes = false;
bool skip_display_connections = false;
std::string version = "0.0.8";
int test_iterations = 5000;

int usage() {
std::cout
Expand All @@ -68,6 +69,7 @@ int usage() {
<< " this option also works for -l_to and "
"-l_from options\n\n"
<< " -test Run some physical tests\n\n"
<< " test_iter=<value> Number of iterations for -test mode\n\n"
<< " -f <filename> Load configuration from file "
<< "./configuration/<filename>\n\n"
<< " -f worm **Load Worm Body Simulation**\n\n"
Expand Down Expand Up @@ -146,9 +148,13 @@ int main(int argc, char **argv) {
if (std::string("-test").compare(argv[i]) == 0) { // run tests
run_tests = true;
}
if (std::string(argv[i]).find("test_iter=") == 0) {
std::string val = std::string(argv[i]).substr(10);
test_iterations = std::stoi(val);
}
}
if (run_tests) {
test_energy_conservation(argc, argv);
test_energy_conservation(argc, argv, test_iterations);
} else

exitStatus = run(argc, argv, graph);
Expand Down
5 changes: 3 additions & 2 deletions src/test/owPhysicTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ float gravity = 9.81f;
* TOTAL ENERGY OF SYSTEM SHOULD BE CONSTANT ALL TIME
* E = mv^2/2 + mgh
* *****************************************************/
void test_energy_conservation(int argc, char **argv) {
void test_energy_conservation(int argc, char **argv, int iterations) {
// owHelper::path = "./configuration/test/"; TODO FIX it
owHelper *helper = new owHelper();
owPhysicsFluidSimulator *fluid_simulation =
Expand All @@ -70,6 +70,7 @@ void test_energy_conservation(int argc, char **argv) {
std::vector<float> energy_evolution_potential;
std::vector<float> energy_evolution_kinetic;
int counter = 0;
int max_iter = iterations > 0 ? iterations : 5000;
std::cout << "==================="
<< "CONSERVATION ENERGY TEST START"
<< "========================" << std::endl;
Expand All @@ -85,7 +86,7 @@ void test_energy_conservation(int argc, char **argv) {
energy_evolution_kinetic.push_back(kinetic_energy);
energy_evolution_potential.push_back(potential_energy);
fluid_simulation->simulationStep();
if (counter == 5000)
if (counter == max_iter)
break;
counter++;
}
Expand Down
51 changes: 51 additions & 0 deletions tests/data/logs/kinetic_energy_distrib.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
0
0
5.71212e-14
3.54781e-13
1.49885e-12
1.43754e-12
1.44832e-12
1.35462e-12
1.25941e-12
1.16405e-12
1.07171e-12
1.01719e-12
9.86021e-13
1.01114e-12
1.0393e-12
1.09286e-12
1.20041e-12
1.28387e-12
1.34602e-12
1.47756e-12
1.51142e-12
1.58781e-12
1.6854e-12
1.7779e-12
1.84796e-12
1.91258e-12
1.95389e-12
2.0489e-12
2.08276e-12
2.12047e-12
2.01053e-12
1.96309e-12
1.96456e-12
1.88864e-12
1.82796e-12
1.82148e-12
1.78353e-12
1.73324e-12
1.684e-12
1.65493e-12
1.59904e-12
1.52696e-12
1.44668e-12
1.40096e-12
1.3702e-12
1.34065e-12
1.3099e-12
1.31751e-12
1.31967e-12
1.31707e-12
1.30362e-12
51 changes: 51 additions & 0 deletions tests/data/logs/potential_energy_distrib.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
2.2121e-12
2.2121e-12
2.21208e-12
2.21203e-12
2.21195e-12
2.21185e-12
2.21171e-12
2.21156e-12
2.21137e-12
2.21116e-12
2.21092e-12
2.21065e-12
2.21036e-12
2.21001e-12
2.20968e-12
2.20935e-12
2.20891e-12
2.20852e-12
2.20807e-12
2.20755e-12
2.20708e-12
2.20654e-12
2.20597e-12
2.2054e-12
2.20483e-12
2.20422e-12
2.2036e-12
2.20285e-12
2.20198e-12
2.20124e-12
2.2005e-12
2.19975e-12
2.19903e-12
2.19823e-12
2.19749e-12
2.19657e-12
2.19558e-12
2.19453e-12
2.19345e-12
2.19246e-12
2.19133e-12
2.19034e-12
2.18926e-12
2.18829e-12
2.18719e-12
2.1861e-12
2.18495e-12
2.18375e-12
2.18251e-12
2.18138e-12
2.18019e-12
Loading