Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
llaniewski committed Dec 19, 2023
2 parents c14b934 + 3d8a6cc commit cfe1311
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 46 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ Developed at:
- [Interdisciplinary Centre for Mathematical and Computational Modelling](https://icm.edu.pl/en) at [University of Warsaw](https://www.uw.edu.pl/)

### Citation
Please use **appropriate citations if using this software** in any research publication. The publication should cite [the original paper about TCLB](https://doi.org/10.1016/j.camwa.2015.12.043) and papers which describe the used LMB models. You can find the list of TCLB publications at [docs.tclb.io/general-info/publications/](https://docs.tclb.io/general-info/publications/). You can also find the information about published articles in the source code of the models.
Please use **appropriate citations if using this software** in any research publication. The publication should cite [the original paper about TCLB](https://doi.org/10.1016/j.camwa.2015.12.043) and papers which describe the used LBM models. You can find the list of TCLB publications at [docs.tclb.io/general-info/publications/](https://docs.tclb.io/general-info/publications/). You can also find the information about published articles in the source code of the models.
The code can be cited additionally, by its [Zenodo DOI](https://doi.org/10.5281/zenodo.3550331).

### License
Expand All @@ -143,4 +143,4 @@ This software is distributed under the [GPL v3 License](LICENSE).

If you need this software under a different license, please contact the main author.

Contact: llaniewski([monkey](https://en.wikipedia.org/wiki/At_sign#Names_in_other_languages))meil.pw.edu.pl
Contact: lukasz.laniewski([monkey](https://en.wikipedia.org/wiki/At_sign#Names_in_other_languages))pw.edu.pl
192 changes: 150 additions & 42 deletions src/Handlers/cbRunR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
#define rNull Rcpp::NumericVector(0)
template <typename T> Rcpp::IntegerVector SingleInteger(T i) { Rcpp::IntegerVector v(1); v[0] = i; return v; }

//RInside RunR::R(0,0,true,false,true);
RInside RunR::R(0,0,true,false,true);

class rWrapper { // Wrapper for all my R objects
public:
Solver * solver;
Expand Down Expand Up @@ -613,48 +610,147 @@ void CLB_WriteConsoleEx( const char* message, int len, int oType ){
}
}

#define R_INTERFACE_PTRS
#include <Rinterface.h>
#define R_INTERFACE_PTRS
#include <Rinterface.h>

int RunR::Init() {
Callback::Init();
notice("R: Initializing R environment ...");

R["CLBFunctionCall"] = Rcpp::InternalFunction( &CLBFunctionCall );
R["$.CLB"] = Rcpp::InternalFunction( &CLBDollar );
R["[[.CLB"] = Rcpp::InternalFunction( &CLBDollar );
R["$<-.CLB"] = Rcpp::InternalFunction( &CLBDollarAssign );
R["print.CLB"] = Rcpp::InternalFunction( &CLBPrint );
R["names.CLB"] = Rcpp::InternalFunction( &CLBNames );
R.parseEval("'CLBFunctionWrap' <- function(obj) { function(...) CLBFunctionCall(obj, list(...)); }");
namespace RunR {
RInside& GetR() {
static RInside * Rptr;
if (Rptr == NULL) {
notice("R: Initializing R environment ...");
Rptr = new RInside(0,0,true,false,true);
RInside& R = *Rptr;

R["CLBFunctionCall"] = Rcpp::InternalFunction( &CLBFunctionCall );
R["$.CLB"] = Rcpp::InternalFunction( &CLBDollar );
R["[[.CLB"] = Rcpp::InternalFunction( &CLBDollar );
R["$<-.CLB"] = Rcpp::InternalFunction( &CLBDollarAssign );
R["[[<-.CLB"] = Rcpp::InternalFunction( &CLBDollarAssign );
R["print.CLB"] = Rcpp::InternalFunction( &CLBPrint );
R["names.CLB"] = Rcpp::InternalFunction( &CLBNames );
R.parseEval("'CLBFunctionWrap' <- function(obj) { function(...) CLBFunctionCall(obj, list(...)); }");
ptr_R_WriteConsoleEx = CLB_WriteConsoleEx ;
ptr_R_WriteConsole = NULL;
R_Outputfile = NULL;
R_Consolefile = NULL;
R.parseEval("options(prompt='[ ] R:> ');");
}
return *Rptr;
};

void parseEval(const std::string& source) {
RInside& R = GetR();
R.parseEval(source);
}

int replInit() {
R_ReplDLLinit();
return 0;
}

int replDo() {
return R_ReplDLLdo1();
}

SEXP wrap_solver(Solver* solver, vHandler * hand) {
rWrapper base;
base.solver = solver;
base.hand = hand;
return base.rWrap(new rSolver ());
}

SEXP wrap_handler(Solver* solver, vHandler * hand, const pugi::xml_node& par) {
rWrapper base;
base.solver = solver;
base.hand = hand;
return base.rWrap(new rXMLNode (par));
}
};

rWrapper base;
base.solver = solver;
base.hand = this;
R["Solver"] = base.rWrap(new rSolver ());
namespace RunPython {
bool has_reticulate = false;
bool py_initialised = false;
void initializePy();

ptr_R_WriteConsoleEx = CLB_WriteConsoleEx ;
ptr_R_WriteConsole = NULL;
R_Outputfile = NULL;
R_Consolefile = NULL;
void parseEval(const std::string& source) {
if (! py_initialised) initializePy();
Rcpp::Function py_run_string("py_run_string");
py_run_string(source);
return;
}

void initializePy() {
RInside& R = RunR::GetR();
has_reticulate = R.parseEval("require(reticulate, quietly=TRUE)");
if (!has_reticulate) throw std::string("Tried to call Python, but no reticulate installed");
py_initialised = true;
R.parseEval(
"py_names = function(obj) names(obj) \n"
"py_element = function(obj, name) `[[`(obj,name) \n"
"py_element_assign = function(obj, name, value) `[[<-`(obj,name,value) \n"
"r_to_py.CLB = function(x, convert=FALSE) py$S3(reticulate:::py_capsule(x))\n"
);
parseEval(
"class S3: \n"
" def __init__(self, obj): \n"
" object.__setattr__(self,'obj',obj) \n"
" def print(self): \n"
" return r.print(self.obj) \n"
" def __dir__(self): \n"
" return r.py_names(self.obj) \n"
" def __getattr__(self, index): \n"
" if index.startswith('_'): \n"
" return None \n"
" return r.py_element(self.obj, index) \n"
" def __setattr__(self, index, value): \n"
" return r.py_element_assign(self.obj, index, value) \n"
" def __call__(self): \n"
" raise TypeError('not really callable') \n"
);
R.parseEval(
"py$Solver = r_to_py(Solver)"
);
}

int replRun() {
if (! py_initialised) initializePy();
Rcpp::Function repl_python("repl_python");
repl_python();
return 0;
}
}

R.parseEval("options(prompt='[ ] R:> ');");
int cbRunR::Init() {
Callback::Init();
RInside& R = RunR::GetR();
R["Solver"] = RunR::wrap_solver(solver,this);

python = false;
interactive = false;
echo = true;

std::string name = node.name();
if (name == "RunPython") python = true;
pugi::xml_attribute attr;
attr = node.attribute("interactive");
if (attr) interactive = attr.as_bool();
attr = node.attribute("echo");
if (attr) echo = attr.as_bool();

s_tag++;
tag = s_tag;

source = "";
for (pugi::xml_node par = node.first_child(); par; par = par.next_sibling()) {
for (pugi::xml_node par = node.first_child(); par; par = par.next_sibling()) {
if (par.type() == pugi::node_element) {
if (python) {
ERROR("Code-embedded xml nodes not supported for python");
return -1;
}
char nd_name[20];
sprintf(nd_name, "xml_%0zx", par.hash_value());
R[nd_name] = base.rWrap(new rXMLNode (par));
R[nd_name] = RunR::wrap_handler(solver,this,par);

source = source + nd_name + "()\n";
output("element\n");
Expand All @@ -668,27 +764,28 @@ int RunR::Init() {
output("Unknown\n");
}
}
// output("----- RunR -----\n");
// output("%s\n",source.c_str());
// output("----------------\n");

if (echo) {
output("-----[ %9s code %03d ]-----\n", node.name(), tag);
output("%s\n",source.c_str());
output("--------------------------------\n");
}
return 0;
}

int cbRunR::s_tag = 0;

int RunR::DoIt() {
int cbRunR::DoIt() {
try {
if (source != "") {
solver->print("Running R ...");
if (echo) {
output("----- RunR -----\n");
output("%s\n",source.c_str());
output("----------------\n");
output("%8d it Executing %s code %03d\n", solver->iter, node.name(), tag);
if (python) {
RunPython::parseEval(source);
} else {
RunR::parseEval(source);
}
R.parseEval(source);
}
if (!interactive) {
if (echo) NOTICE("You can run interactive R session with Ctrl+X");
if (echo) NOTICE("You can run interactive %s session with Ctrl+X", node.name());
int c = kbhit();
if (c == 24) {
int a = getchar();
Expand All @@ -698,10 +795,21 @@ int RunR::DoIt() {
}
}
if (interactive) {
R_ReplDLLinit();
while( R_ReplDLLdo1() > 0 ) {}
if (python) {
RunPython::replRun();
} else {
RunR::replInit();
while( RunR::replDo() > 0 ) {}
}
}
} catch (Rcpp::exception& ex) {
ERROR("Caught Rcpp exception");
return -1;
} catch(std::exception &ex) {
ERROR("Caught std exception: %s", ex.what());
return -1;
} catch (...) {
ERROR("Caught uknown exception");
return -1;
}
return 0;
Expand All @@ -713,9 +821,9 @@ int RunR::DoIt() {
// Function created only to check to create Handler for specific conditions
vHandler * Ask_For_RunR(const pugi::xml_node& node) {
std::string name = node.name();
if (name == "RunR") {
if (name == "RunR" || name == "RunPython") {
#ifdef WITH_R
return new RunR;
return new cbRunR;
#else
ERROR("No R support. configure with --enable-rinside\n");
exit(-1);
Expand Down
6 changes: 4 additions & 2 deletions src/Handlers/cbRunR.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@

#ifdef WITH_R

class RunR : public Callback {
class cbRunR : public Callback {
std::string source;
bool interactive;
bool echo;
bool python;
static int s_tag;
int tag;
public:
static RInside R;
int Init ();
int DoIt ();
};
Expand Down

0 comments on commit cfe1311

Please sign in to comment.