1 #include "properties/Distributable.hh"
2 #include "properties/IndexInherit.hh"
3 #include "properties/CommutingAsProduct.hh"
4 #include "properties/DependsInherit.hh"
5 #include "properties/NumericalFlat.hh"
6 #include "properties/WeightInherit.hh"
7 #include "properties/CommutingAsSum.hh"
8 #include "properties/Derivative.hh"
9 #include "properties/Accent.hh"
10 #include "properties/Tableau.hh"
11 #include "properties/FilledTableau.hh"
12 
13 #include "CdbPython.hh"
14 
15 #include "py_globals.hh"
16 #include "py_helpers.hh"
17 #include "py_kernel.hh"
18 #include "py_ex.hh"
19 
20 namespace cadabra {
create_scope()21 	Kernel *create_scope()
22 		{
23 		Kernel *k = new Kernel(true);
24 		return k;
25 		}
26 
create_scope_from_global()27 	Kernel *create_scope_from_global()
28 		{
29 		Kernel *k = create_empty_scope();
30 		// FIXME: copy global properties
31 		return k;
32 		}
33 
create_empty_scope()34 	Kernel *create_empty_scope()
35 		{
36 		Kernel *k = new Kernel(false);
37 		return k;
38 		}
39 
get_kernel_from_scope()40 	Kernel *get_kernel_from_scope()
41 		{
42 		Kernel *kernel = nullptr;
43 
44 		// Try and find the kernel in the local scope
45 		auto locals = get_locals();
46 		if (locals && scope_has(locals, "__cdbkernel__")) {
47 			kernel = locals["__cdbkernel__"].cast<Kernel*>();
48 			return kernel;
49 			}
50 
51 		// No kernel in local scope, find one in global scope.
52 		auto globals = get_globals();
53 		if (globals && scope_has(globals, "__cdbkernel__")) {
54 			kernel = globals["__cdbkernel__"].cast<Kernel*>();
55 			return kernel;
56 			}
57 
58 		// No kernel in local or global scope, construct a new global one
59 		kernel = create_scope();
60 		globals["__cdbkernel__"] = kernel;
61 		return kernel;
62 		}
63 
init_kernel(pybind11::module & m)64 	void init_kernel(pybind11::module& m)
65 		{
66 		// Declare the Kernel object for Python so we can store it in the local Python context.
67 		// We add a 'cadabra2.__cdbkernel__' object to the main module scope, and will
68 		// pull that into the interpreter scope in the 'cadabra2_default.py' file.
69 		pybind11::enum_<Kernel::scalar_backend_t>(m, "scalar_backend_t")
70 		.value("sympy", Kernel::scalar_backend_t::sympy)
71 		.value("mathematica", Kernel::scalar_backend_t::mathematica)
72 		.export_values();
73 
74 		pybind11::class_<Kernel>(m, "Kernel", pybind11::dynamic_attr())
75 		.def(pybind11::init<bool>())
76 			.def_readonly_static("version",        &Kernel::version)
77 			.def_readonly_static("build",          &Kernel::build)
78 			.def_readonly("scalar_backend", &Kernel::scalar_backend);
79 
80 		Kernel* kernel = create_scope();
81 		m.attr("__cdbkernel__") = pybind11::cast(kernel);
82 
83 		m.def("kernel", [](pybind11::kwargs dict) {
84 			Kernel *k = get_kernel_from_scope();
85 			for (auto& item : dict) {
86 				std::string key = item.first.cast<std::string>();
87 				if (key == "scalar_backend") {
88 					std::string val = item.second.cast<std::string>();
89 					if (val == "sympy")            k->scalar_backend = Kernel::scalar_backend_t::sympy;
90 					else if (val == "mathematica") k->scalar_backend = Kernel::scalar_backend_t::mathematica;
91 					else throw ArgumentException("scalar_backend must be 'sympy' or 'mathematica'.");
92 					}
93 				else if(key == "call_embedded_python_functions") {
94 					bool val = item.second.cast<bool>();
95 					k->call_embedded_python_functions=val;
96 					}
97 				else {
98 					throw ArgumentException("unknown argument '" + key + "'.");
99 					}
100 				}
101 			});
102 
103 		m.def("create_scope", &create_scope,
104 		      pybind11::return_value_policy::take_ownership);
105 		m.def("create_scope_from_global", &create_scope_from_global,
106 		      pybind11::return_value_policy::take_ownership);
107 		m.def("create_empty_scope", &create_empty_scope,
108 		      pybind11::return_value_policy::take_ownership);
109 
110 		m.def("cdb2python", &cdb2python);
111 		m.def("cdb2python_string", &cdb2python_string);
112 		}
113 
114 	}
115