executeIfPythonFunctionObject::executeIfPythonFunctionObject
(
    const word& name,
    const Time& t,
    const dictionary& dict
)
:
    conditionalFunctionObjectListProxy(
        name,
        t,
        dict
    ),
    pythonInterpreterWrapper(
        t.db(),
        dict
    )
{
    if(!parallelNoRun()) {
        initEnvironment(t);

        setRunTime(t);
    }

    readParameters(dict);
}
pythonFluIntegrationFunctionObject::pythonFluIntegrationFunctionObject
(
    const word& name,
    const Time& t,
    const dictionary& dict
)
    :
    pythonIntegrationFunctionObject(name,t,dict)
{
    if(parallelNoRun()) {
        return;
    }

    if(!executeCode("import Foam",false)) {
        FatalErrorIn("pythonFluIntegrationFunctionObject::pythonFluIntegrationFunctionObject")
                << "Python can not import module Foam. Probably no pythonFlu installed"
                << endl
                << exit(FatalError);
    }
    executeCode("import Foam.OpenFOAM as OpenFOAM",false,true);
    executeCode("import Foam.finiteVolume as finiteVolume",false,true);

    executeCode("from Foam.integrationHelpers.getObjectsFromPointers import getTimeFromPtr",false,true); // this should work, but doesn't
    // executeCode("from Foam.src.OpenFOAM.db.Time.Time import getTimeFromPtrOld as getTimeFromPtr",false,true); // This works

    PyObject *time=PyCObject_FromVoidPtr((void*)(&t),NULL);

    PyObject *m = PyImport_AddModule("__main__");
    PyObject_SetAttrString(m,"theTime",time);
    executeCode("time=getTimeFromPtr(theTime)",true,false);

    // Get rid of the helper stuff
    PyRun_SimpleString("del theTime");
    PyRun_SimpleString("del getTimeFromPtr");
}
bool pythonIntegrationFunctionObject::end()
{
    Pbug << "end" << endl;

    if(!parallelNoRun()) {
        setRunTime();
    }

    return executeCode(endCode_,true);
}
luaInterpreterWrapper::~luaInterpreterWrapper()
{
    if(parallelNoRun()) {
        return;
    }

    if(luaState_){
        lua_close(luaState_);
    }
}
bool pythonIntegrationFunctionObject::start()
{
    Pbug << "start" << endl;

    simpleFunctionObject::start();

    if(!parallelNoRun()) {
        setRunTime();
    }

    return executeCode(startCode_,true);
}
void pythonIntegrationFunctionObject::writeSimple()
{
    Pbug << "writeSimple" << endl;

    if(!parallelNoRun()) {
        setRunTime();
    }

    executeCode(executeCode_,true);

    if(this->time_.outputTime()) {
        executeCode(writeCode_,true);
    }
}
bool executeIfPythonFunctionObject::condition()
{
    if(!parallelNoRun()) {
        setRunTime(time());
    }

    if(writeDebug()) {
        Info << "Evaluating " << conditionCode_ << endl;
    }
    bool result=evaluateCodeTrueOrFalse(conditionCode_,true);
    if(writeDebug()) {
        Info << "Evaluated to " << result << endl;
    }
    return result;
}
timeManipulationWithPythonFunctionObject::timeManipulationWithPythonFunctionObject
(
    const word &name,
    const Time& t,
    const dictionary& dict
)
:
    timeManipulationFunctionObject(name,t,dict),
    pythonInterpreterWrapper(
        t.db(),
        dict
    )
{
    if(!parallelNoRun()) {
        initEnvironment(t);

        setRunTime(t);
    }
}
bool writeAndEndPythonFunctionObject::endRunNow()
{
    if(!parallelNoRun()) {
        setRunTime(time());
    }

    if(writeDebug()) {
        Info << "Evaluating " << conditionCode_ << endl;
    }
    bool result=evaluateCodeTrueOrFalse(conditionCode_,true);
    if(writeDebug()) {
        Info << "Evaluated to " << result << endl;
    }

    if(result) {
        Info << "Stopping because python code  " << conditionCode_
            << " evaluated to 'true' in " << name() << endl;
    }

    return result;
}
writeAndEndPythonFunctionObject::writeAndEndPythonFunctionObject
(
    const word &name,
    const Time& t,
    const dictionary& dict
)
:
    writeAndEndFunctionObject(name,t,dict),
    pythonInterpreterWrapper(
        t.db(),
        dict
    )
{
    if(!parallelNoRun()) {
        initEnvironment(t);

        setRunTime(t);
    }

    readParameters(dict);
}
pythonIntegrationFunctionObject::pythonIntegrationFunctionObject
(
    const word& name,
    const Time& t,
    const dictionary& dict
)
:
    simpleFunctionObject(
        name,
        t,
        dict
    ),
    pythonInterpreterWrapper(
        t.db(),
        dict
    ),
    time_(t)
{
    Pbug << "Constructor" << endl;

    if(!parallelNoRun()) {
        initEnvironment(t);

        setInterpreter();
        PyObject *m = PyImport_AddModule("__main__");
        PyObject_SetAttrString(
            m,
            "functionObjectName",
            PyString_FromString(this->name().c_str())
        );
        releaseInterpreter();

        setRunTime();
    }

    read(dict);
}
scalar setDeltaTWithPythonFunctionObject::deltaT()
{
    if(!parallelNoRun()) {
        setRunTime(time());
    }

    if(writeDebug()) {
        Pbug << "Evaluating " << deltaTCode_ << endl;
    }

    scalar result=evaluateCodeScalar(deltaTCode_,true);

    if(writeDebug()) {
        Pbug << "Evaluated to " << result << endl;
    }

    if(result!=time().deltaT().value()) {
        Info << "Changing timestep because " << deltaTCode_
            << " evaluated to " << result << "(current deltaT: "
            << time().deltaT().value() << " in " << name() << endl;
    }

    return result;
}
pythonInterpreterWrapper::pythonInterpreterWrapper
(
    const objectRegistry& obr,
    const dictionary& dict,
    bool forceToNamespace
):
    generalInterpreterWrapperCRTP<pythonInterpreterWrapper>(
        obr,
        dict,
        forceToNamespace,
        "python"
    ),
    pythonState_(NULL),
    useNumpy_(dict.lookupOrDefault<bool>("useNumpy",true)),
    useIPython_(dict.lookupOrDefault<bool>("useIPython",true)),
    triedIPython_(false),
    oldIPython_(false)
{
    if(generalInterpreterWrapper::debug>debug) {
        debug=1;
    }

    Pbug << "Starting constructor" << endl;

    syncParallel();

#ifdef FOAM_HAS_LOCAL_DEBUGSWITCHES
    debug=dict.lookupOrDefault<label>("debugPythonWrapper",debug());
#else
    debug=dict.lookupOrDefault<label>("debugPythonWrapper",debug);
#endif

    if(!dict.found("useNumpy")) {
        WarningIn("pythonInterpreterWrapper::pythonInterpreterWrapper")
            << "Switch 'useNumpy' not found in " << dict.name() << nl
                << "Assuming it to be 'true' (if that is not what you want "
                << "set it. Also set it to make this warning go away)"
                << endl;
    }

    if(!dict.found("useIPython")) {
        WarningIn("pythonInterpreterWrapper::pythonInterpreterWrapper")
            << "Switch 'useIPython' not found in " << dict.name() << nl
                << "Assuming it to be 'true' (if that is not what you want "
                << "set it. Also set it to make this warning go away)"
                << endl;
    }

    if(interpreterCount==0) {
        Pbug << "Initializing Python" << endl;

        Py_Initialize();

        if(debug) {
            PyThreadState *current=PyGILState_GetThisThreadState();
            Pbug << "GIL-state before thread" << getHex(current) << endl;
        }
        PyEval_InitThreads();
         if(debug) {
            PyThreadState *current=PyGILState_GetThisThreadState();
            Pbug << "GIL-state after thread" << getHex(current) << endl;
        }
        // importLib("scipy.stats","stats"); - OK
        mainThreadState = PyEval_SaveThread();
        // importLib("scipy.stats","stats"); - segFault

        Pbug << "Main thread state: " << getHex(mainThreadState) << endl;
        // PyRun_SimpleString("import IPython\n" // here it works as expected
        // "IPython.embed()\n");
    }

    if(Pstream::parRun()) {
        Pbug << "This is a parallel run" << endl;

        parallelMasterOnly_=readBool(dict.lookup("parallelMasterOnly"));
    }

    if(parallelNoRun(true)) {
        Pbug << "Getting out because of 'parallelNoRun'" << endl;
        return;
    }

    interpreterCount++;

    Pbug << "Getting new interpreter" << endl;
    pythonState_=Py_NewInterpreter();
    Pbug << "Interpreter state: " << getHex(pythonState_) << endl;

    //    interactiveLoop("Clean");

    initIPython();

    Pbug << "Currently " << interpreterCount
        << " Python interpreters (created one)" << endl;

    if(
        interactiveAfterExecute_
        ||
        interactiveAfterException_
    ) {
    } else {
        if(useIPython_) {
            WarningIn("pythonInterpreterWrapper::pythonInterpreterWrapper")
                << "'useIPython' not needed in " << dict.name()
                    << " if there is no interactivity"
                    << endl;
        }
    }

    if(useNumpy_) {
        Dbug << "Attempting to import numpy" << endl;

        static bool warnedNumpy=false;
        if(!warnedNumpy) {
            if(getEnv("FOAM_SIGFPE")!="false") {
                WarningInFunction
                    << "Attempting to import numpy. On some platforms that will raise a "
                        << "(harmless) floating point exception. To avoid switch off "
                        << "by setting the environment variable 'FOAM_SIGFPE' to 'false'"
                        << endl;
            }
            warnedNumpy=true;
        }

        int fail=!importLib("numpy");
        if(fail) {
            FatalErrorIn("pythonInterpreterWrapper::pythonInterpreterWrapper")
                << "Problem during import of numpy." << nl
                    << "Switch if off with 'useNumpy false;' if it is not needed"
                    << endl
                    << exit(FatalError);
        }
        fail=PyRun_SimpleString(
            // "def _swak_wrapOpenFOAMField_intoNumpy(address,typestr,size,nr=None):\n"
            // "   class iWrap(object):\n"
            // "      def __init__(self):\n"
            // "         self.__array_interface__={}\n"
            // "         self.__array_interface__['data']=(int(address,16),False)\n"
            // "         if nr:\n"
            // "             self.__array_interface__['shape']=(size,nr)\n"
            // "         else:\n"
            // "             self.__array_interface__['shape']=(size,)\n"
            // "         self.__array_interface__['version']=3\n"
            // "         self.__array_interface__['typestr']=typestr\n"
            // "   return numpy.asarray(iWrap())\n"
            "class OpenFOAMFieldArray(numpy.ndarray):\n"
            "   def __new__(cls,address,typestr,size,nr=None,names=None):\n"
            "      obj=type('Temporary',(object,),{})\n"
            "      obj.__array_interface__={}\n"
            "      obj.__array_interface__['data']=(address,False)\n"
            "      if nr:\n"
            "          obj.__array_interface__['shape']=(size,nr)\n"
            "      else:\n"
            "          obj.__array_interface__['shape']=(size,)\n"
            //            "      obj.__array_interface__['descr']=[('x',typestr)]\n"
            "      obj.__array_interface__['version']=3\n"
            "      obj.__array_interface__['typestr']=typestr\n"
            "      obj=numpy.asarray(obj).view(cls)\n"
            "      if names:\n"
            "         for i,n in enumerate(names):\n"
            "            def f(ind):\n"
            "               return obj[:,ind]\n"
            "            setattr(obj,n,f(i))\n"
            "      return obj\n"
            "   def __array_finalize__(self,obj):\n"
            "      if obj is None: return\n"
        );
    }

    if(dict.found("importLibs")) {
        const dictionary &libList=dict.subDict("importLibs");
        forAllConstIter(dictionary,libList,iter) {
            word as=(*iter).keyword();
            word full((*iter).stream());
            if(full=="") {
                full=as;
            }
            importLib(full,as,true);
        }
    } else {