Hello Louis,
It took a bit of time to test and prepare, but here I am going to show you how can you do this. First, you must load the NRG file into the System class:
-------
#include <cmath>
#include <cassert>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <cstring>
#include <stdexcept>
#include <cstdlib>
#include "io_tools/read_nrg.h"
#include "io_tools/write_nrg.h"
#include "bblock/system.h"
//#define PRINT_GRADS
namespace {
static std::vector<bblock::System> systems;
} // namespace
int main(int argc, char** argv) {
// Check number of arguments
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <input.nrg> [mbx.json]" << std::endl;
return 0;
}
// Load the nrg file
try {
std::ifstream ifs(argv[1]);
if (!ifs) {
throw std::runtime_error("could not open the NRG file");
}
tools::ReadNrg(argv[1], systems);
ifs.close();
} catch (const std::exception& e) {
std::cerr << " ** Error ** : " << e.what() << std::endl;
return 1;
}
// Load JSON file
std::vector<double> box;
for (size_t i = 0; i < systems.size(); i++) {
if (argc > 2) {
systems[i].SetUpFromJson(argv[2]);
} else {
systems[i].SetUpFromJson();
}
}
------
This code snippet will read a the NRG file and the JSON file form command line arguments of this executable. At this point, you can set the electric fields. You must have a vector of length N_SITES (System.GetNumSites() will give you that number) with the magnitude of the field at the position of each site, and a vector of length 3*N_SITES with the electric field at each position. Let's call them "phi" and "efield". You can set those in the system with:
System.SetExternalElectrostaticPotentialAndFieldInSites(phi,efield)
And then you can just calculate the energy
System.Energy(True)
And if you want to retrieve the atomic dipoles, just call the function:
System.GetDipoles(mu_perm, mu_ind)
Which will fill the mu_perm with the permanent dipoles (q*r) and mu_ind with the induced dipoles.
If you want to compare dipoles before and after the field is added:
e_nofield = systems[0].Energy(True);
systems[0].GetDipoles(mu_perm_nofield, mu_ind_nofield);
systems[0].SetExternalElectrostaticPotentialAndFieldInSites(phi,efield)
e_field = systems[0].Energy(True);
systems[0].GetDipoles(mu_perm_field, mu_ind_field);
I hope this helps you a bit. I know that the python interface may be easier to code, but you will have more flexibility with the C++.
Let me know if there are any other issues or questions!