Week 2: Into the Lua Bindings

ruhi
Published: 06/07/2023

Overview

I have been going over the source code of d-SEAMS and puzzling out the minimal required objects and functions. It seems that for the `lua` bindings, the objects were mostly constructed in `C++` and then populated in `lua`, however, for the `python` bindings each class will need to have separate bindings. I have narrowed my focus to a single workflow, not the entire driver (which is controlled by the `yaml` file), that is as discussed in the paper (from here):

```cpp
if (config["topoTwoDim"]["use"].as<bool>()) {
    // Use the variables script
    lua.script_file(vars);
    // -----------------
    // Variables which must be declared in C++
    //
    // Newer pointCloud (rescloud -> ice structure, solcloud -> largest cluster)
    molSys::PointCloud<molSys::Point<double>, double> resCloud;
    // Some neighbor lists
    std::vector<std::vector<int>> nList, hbnList;
    // For the list of all rings (of all sizes)
    std::vector<std::vector<int>> ringsAllSizes;
    std::vector<std::vector<int>> rings;
    // RDF stuff
    std::vector<double> rdfValues; // RDF vector
    // -----------------
    // This section basically only registers functions and handles the rest in
    // lua Use the functions defined here
    auto lscript = lua.get<std::string>("functionScript");
    // Transfer variables to lua
    lua["doBOP"] = config["bulk"]["use"].as<bool>();
    lua["topoOneDim"] = config["topoOneDim"]["use"].as<bool>();
    lua["topoTwoDim"] = config["topoTwoDim"]["use"].as<bool>();
    lua["topoBulk"] = config["bulk"]["use"].as<bool>();
    //
    lua["nList"] = &nList;
    lua["hbnList"] = &hbnList;
    lua["resCloud"] = &resCloud;
    lua["trajectory"] = tFile;
    // Confined ice stuff
    lua["ringsAllSizes"] = &rings;
    // RDF stuff
    lua["rdf"] = &rdfValues;
    // -----------------
    // Register functions
    //
    // Writing stuff
    // Generic requirements
    lua.set_function("readFrameOnlyOne", sinp::readLammpsTrjreduced);
    lua.set_function("readFrameOnlyOneAllAtoms", sinp::readLammpsTrj); // reads in all atoms regardless of type  
    lua.set_function("neighborList", nneigh::neighListO);
    // -----------------
    // Topological Network Method Specific Functions
    // Generic requirements (read in only inside the slice)
    lua.set_function("getHbondNetwork", bond::populateHbonds);
    lua.set_function("bondNetworkByIndex", nneigh::neighbourListByIndex);
    // -----------------
    // Primitive rings
    lua.set_function("getPrimitiveRings", primitive::ringNetwork);
    // -----------------
    // Quasi-two-dimensional ice
    lua.set_function("ringAnalysis", ring::polygonRingAnalysis);
    // --------------------------
    // RDF functions
    lua.set_function("calcRDF", rdf2::rdf2Danalysis_AA);
    // --------------------------
    // Use the script
    lua.script_file(lscript);
    // --------------------------
  } // end of two-dimensional ice block
```

It is clear that the bindings might be a mite more complicated in `python`, especially as I realized many of the core structures are templated.

Check-in Questions

What did you do this week?

  • Went over the `d-seams` documentation and examples locally
    • Settled on a workflow to bind
    • Looked into the classes and functions needed
  • Went over the `sol3` documentation on the `lua` bindings

What is coming up next?

1.  I intend to have a personal site with more details of the internals
2. I shall start designing the code and determine a style guide with my mentor
3. I will finish enumerating the functions and objects needed to be bound for this workflow

Did you get stuck anywhere?

I was a bit confused about the manner in which memory was managed between `lua` and `cpp` and how it would change with the `python` bindings. I hope to clarify this further, and have a minimal toy setup on my machine to work with when I meet my mentor later this week.