Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
db670c2
Initial commit: fix assembly of molecular diffusion
av-novikov Sep 30, 2024
6833041
Reorganize MultivariableTableFunctionKernels, change name to Multilin…
av-novikov Oct 2, 2024
9c9e28e
Introduce multilinear adaptive interpolation kernel
av-novikov Oct 7, 2024
585337f
Draft of adaptive multilinear interpolator test
av-novikov Oct 7, 2024
3d931f1
Introduce convergence test for multilinear adaptive interpolator
av-novikov Oct 8, 2024
2dfae1a
Fix integer overflow - use __uint128_t for indexation
av-novikov Oct 8, 2024
d36873f
Add descriptions of some methods
av-novikov Oct 9, 2024
ada5e41
Use only two resolutions in convergence test of multilinear adaptive …
av-novikov Oct 9, 2024
5d12ee9
Small fix of include declarations
av-novikov Oct 9, 2024
c8bed1a
Introduce OBLFluid constitutive
av-novikov Oct 9, 2024
16542ba
Move hypercube and point data storage from adaptive interpolation ker…
av-novikov Oct 9, 2024
4df5792
Initialize PythonFunction in OBLFluid, OBL axes parameters are moved …
av-novikov Oct 10, 2024
c06e8d8
Check if Python function actually assigned to wrapper before launchin…
av-novikov Oct 10, 2024
39b2a3c
Expose PythonFunction interfaces to Python
av-novikov Oct 10, 2024
f6fa56d
Create a source file for PythonFunction
av-novikov Oct 16, 2024
e98dd33
Update OBL static models
av-novikov Oct 17, 2024
052dee6
Add an example of Python-based model with interfaces from Makutu team
av-novikov Oct 17, 2024
c48636e
Use LvArray::python::PythonFunction
av-novikov Oct 18, 2024
c5c67f2
Recover adaptive interpolation test
av-novikov Oct 18, 2024
28bfa6a
Suppress unused parameter error
av-novikov Oct 21, 2024
a6f9750
Merge branch develop into feature/anovikov/adaptive_obl
av-novikov Oct 21, 2024
023ef96
Move Python interfaces to GEOS, merge obl example into a single script
av-novikov Oct 21, 2024
b5d8931
Update LvArray commit
av-novikov Oct 21, 2024
583e6b6
Uncrustify formatting
av-novikov Oct 24, 2024
ed6c873
Move new Python interfaces to geosPythonPackages -> pygeos-tools
av-novikov Oct 30, 2024
3d606c8
Merge branch 'develop' into feature/anovikov/adaptive_obl
av-novikov Oct 30, 2024
c3843fc
Create a base XML file for model example
av-novikov Feb 25, 2025
fc52d93
Applying changes from review
av-novikov Feb 26, 2025
9e1ee77
Fix OBL solver according to changes in open-darts operators, fix asse…
av-novikov Mar 18, 2025
4110b43
Introduce number of solid components and adjust chopping accordingly
av-novikov Mar 18, 2025
612865d
PHREEQC-based limestone dissolution by carbonated water: 1D and 2D se…
av-novikov Mar 31, 2025
88f4f71
Clean up OBL examples, they are moved to geosPythonPackages
av-novikov Apr 17, 2025
defed93
Merge branch develop into feature/anovikov/adaptive_obl
av-novikov Apr 21, 2025
ab1733f
Fix FunctionManager::createChild
av-novikov Apr 23, 2025
c6b8ad8
Fix dangling references in MultifluidTest.hpp
av-novikov Apr 23, 2025
b5d4dc0
Merge branch 'develop' into feature/anovikov/adaptive_obl
rrsettgast Apr 25, 2025
aeb36fa
Receive cycleNumber from Python in output/execute/collect calls
av-novikov Apr 24, 2025
3c66fdc
Uncrustify formatting
av-novikov Apr 24, 2025
b4a296b
Update LvArray
av-novikov Apr 25, 2025
e16b427
Remove commented code from OBLFluid.cpp
av-novikov Apr 25, 2025
5f95af0
Simplify logic for deducing m_intepolatorType as only multilinear one…
av-novikov Apr 25, 2025
76559a8
Impose GEOS_USE_PYGEOSX/ENABLE_PYGEOSX guards for Python-dependent fu…
av-novikov Apr 28, 2025
afca323
Uncrustify check
av-novikov Apr 28, 2025
3ea2b41
Merge develop
av-novikov Sep 3, 2025
de5e78a
Fix includes
av-novikov Sep 12, 2025
ffef26d
Merge branch 'develop' into feature/anovikov/adaptive_obl
av-novikov Sep 12, 2025
6076912
Switch to True-IMPES reduction and Galerkin coarse grid method
av-novikov Sep 12, 2025
0ae76ee
Update OBL operators, use MULT_OP instead of hardcoded power law for …
av-novikov Nov 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Expose PythonFunction interfaces to Python
  • Loading branch information
av-novikov committed Oct 10, 2024
commit 39b2a3c14bff3b7a49311670b9e55d6bb046d895
8 changes: 8 additions & 0 deletions src/coreComponents/functions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ if( ENABLE_MATHPRESSO )
list( APPEND dependencyList mathpresso )
endif()

if( ENABLE_PYGEOSX )
list( APPEND functions_headers
python/PyPythonFunctionType.hpp )
list( APPEND functions_sources
python/PyPythonFunction.cpp )
list( APPEND dependencyList Python3::Python pylvarray )
endif()

geos_decorate_link_dependencies( LIST decoratedDependencies
DEPENDENCIES ${dependencyList} )

Expand Down
15 changes: 15 additions & 0 deletions src/coreComponents/functions/PythonFunction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#include "common/DataTypes.hpp"
#include "dataRepository/Group.hpp"

#if defined(GEOS_USE_PYGEOSX)
#include "python/PyPythonFunctionType.hpp"
#endif

namespace std
{
template <>
Expand Down Expand Up @@ -416,6 +420,17 @@ class PythonFunction : public dataRepository::Group
* @return a reference to an array of table axes hypercube index multiplicators
*/
arrayView1d< __uint128_t const > getAxisHypercubeMults() const { return m_axisHypercubeMults.toViewConst(); }

#if defined(GEOS_USE_PYGEOSX)
/**
* @brief Return PySolver type.
* @return Return PySolver type.
*/
virtual PyTypeObject * getPythonType() const override
{
return python::getPyPythonFunctionType();
}
#endif
private:
/// Array [numDims] of axis minimum values
array1d<real64> m_axisMinimums;
Expand Down
206 changes: 206 additions & 0 deletions src/coreComponents/functions/python/PyPythonFunction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/*
* ------------------------------------------------------------------------------------------------------------
* SPDX-License-Identifier: LGPL-2.1-only
*
* Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
* Copyright (c) 2018-2024 Total, S.A
* Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2023-2024 Chevron
* Copyright (c) 2019- GEOS/GEOSX Contributors
* All rights reserved
*
* See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
* ------------------------------------------------------------------------------------------------------------
*/

// Python.h must be included first.
#define PY_SSIZE_T_CLEAN
#include <Python.h>

// Source includes
#include "LvArray/src/python/pythonHelpers.hpp"
#include "functions/PythonFunction.hpp"
#include "PyPythonFunctionType.hpp"
#include "dataRepository/python/PyGroupType.hpp"


#define VERIFY_NON_NULL_SELF( self ) \
PYTHON_ERROR_IF( self == nullptr, PyExc_RuntimeError, "Passed a nullptr as self.", nullptr )

#define VERIFY_INITIALIZED( self ) \
PYTHON_ERROR_IF( self->group == nullptr, PyExc_RuntimeError, "The PyPythonFunction is not initialized.", nullptr )

namespace geos
{
namespace python
{

struct PyPythonFunction
{
PyObject_HEAD

static constexpr char const * docString =
"A Python interface to geos::PythonFunction.";

geos::PythonFunction<> * group;
};


/**
* @brief Allocate a new PyPythonFunction object
*/
static PyObject * PyPythonFunction_new( PyTypeObject *type, PyObject *args, PyObject *kwds )
{
GEOS_UNUSED_VAR( args, kwds );
PyPythonFunction *self;

// Allocate memory for the Python object
self = (PyPythonFunction *)type->tp_alloc( type, 0 );
if( self != nullptr )
{
self->group = nullptr; // Initialize the pyFunc to nullptr (not yet assigned)
}

return (PyObject *)self;
}
/**
* @brief String representation of PyPythonFunction object
*/
static PyObject * PyPythonFunction_repr( PyObject * const obj ) noexcept
{
PyPythonFunction const * const pyPythonFunc = reinterpret_cast<PyPythonFunction *>( obj );
if( pyPythonFunc == nullptr )
{
return nullptr;
}

VERIFY_INITIALIZED( pyPythonFunc );

std::string const path = pyPythonFunc->group->getPath(); // Assuming PythonFunction has getPath()
std::string const type = LvArray::system::demangle( typeid( *(pyPythonFunc->group) ).name() );
std::string const repr = path + " ( " + type + " )";

return PyUnicode_FromString( repr.c_str() );
}
/**
* @brief Expose the setAxes function to Python
*/
static PyObject* PyPythonFunction_setAxes(PyPythonFunction* self, PyObject* args)
{
VERIFY_NON_NULL_SELF( self );
VERIFY_INITIALIZED( self );

PythonFunction<>* func = self->group;

if (func == nullptr)
{
PyErr_SetString(PyExc_RuntimeError, "Not a valid PythonFunction instance.");
return nullptr;
}

// Parse arguments
integer numDims, numOps;
PyObject *axisMinList, *axisMaxList, *axisPointsList;

if (!PyArg_ParseTuple(args, "iiOOO", &numDims, &numOps, &axisMinList, &axisMaxList, &axisPointsList))
{
return nullptr;
}

// Check list lengths
if (PyList_Size(axisMinList) != numDims || PyList_Size(axisMaxList) != numDims || PyList_Size(axisPointsList) != numDims)
{
PyErr_SetString(PyExc_ValueError, "List lengths do not match numDims.");
return nullptr;
}

// Convert Python lists to internal array representations
real64_array axisMinimums(numDims);
real64_array axisMaximums(numDims);
integer_array axisPoints(numDims);

for (integer i = 0; i < numDims; ++i)
{
axisMinimums[i] = PyFloat_AsDouble(PyList_GetItem(axisMinList, i));
axisMaximums[i] = PyFloat_AsDouble(PyList_GetItem(axisMaxList, i));
axisPoints[i] = PyLong_AsLong(PyList_GetItem(axisPointsList, i));
}

// Call the C++ function to set axes
func->setAxes(numDims, numOps, axisMinimums, axisMaximums, axisPoints);

Py_RETURN_NONE;
}

/**
* @brief Expose the setEvaluateFunction function to Python
*/
static PyObject* PyPythonFunction_setEvaluateFunction(PyPythonFunction* self, PyObject* args)
{
VERIFY_NON_NULL_SELF( self );
VERIFY_INITIALIZED( self );

PythonFunction<>* func = self->group;

if (func == nullptr)
{
PyErr_SetString(PyExc_RuntimeError, "Not a valid PythonFunction instance.");
return nullptr;
}

PyObject* pyFuncObj;

if (!PyArg_ParseTuple(args, "O", &pyFuncObj))
{
return nullptr;
}

// Ensure pyFuncObj is callable
if (!PyCallable_Check(pyFuncObj))
{
PyErr_SetString(PyExc_TypeError, "Argument must be callable.");
return nullptr;
}

// Call the C++ function to set the evaluate function
func->setEvaluateFunction(pyFuncObj);

Py_RETURN_NONE;
}

static PyMethodDef PyPythonFunction_methods[] = {
{ "setAxes", (PyCFunction) PyPythonFunction_setAxes, METH_VARARGS, "Set axes for the Python function." },
{ "setEvaluateFunction", (PyCFunction) PyPythonFunction_setEvaluateFunction, METH_VARARGS, "Set Python evaluate function and optionally a derivative function." },
{ nullptr, nullptr, 0, nullptr } // Sentinel
};

/**
* Initialize the module object for Python with the exported functions
*/

BEGIN_ALLOW_DESIGNATED_INITIALIZERS

static PyTypeObject PyPythonFunctionType = {
PyVarObject_HEAD_INIT(nullptr, 0)
.tp_name = "pygeosx.PythonFunction",
.tp_basicsize = sizeof(PyPythonFunction),
.tp_repr = PyPythonFunction_repr,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_doc = PyPythonFunction::docString,
.tp_methods = PyPythonFunction_methods,
.tp_base = getPyGroupType(),
.tp_new = PyPythonFunction_new,
};

END_ALLOW_DESIGNATED_INITIALIZERS

/**
* Return the PyTypeObject for PyPythonFunction
*/
PyTypeObject * getPyPythonFunctionType()
{
return &PyPythonFunctionType;
}

} // namespace python
} // namespace geos
31 changes: 31 additions & 0 deletions src/coreComponents/functions/python/PyPythonFunctionType.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* ------------------------------------------------------------------------------------------------------------
* SPDX-License-Identifier: LGPL-2.1-only
*
* Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
* Copyright (c) 2018-2024 Total, S.A
* Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
* Copyright (c) 2023-2024 Chevron
* Copyright (c) 2019- GEOS/GEOSX Contributors
* All rights reserved
*
* See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
* ------------------------------------------------------------------------------------------------------------
*/

#ifndef GEOS_PYTHON_PYPYTHONFUNCTIONTYPE_HPP_
#define GEOS_PYTHON_PYPYTHONFUNCTIONTYPE_HPP_

#include "LvArray/src/python/pythonForwardDeclarations.hpp"

namespace geos
{
namespace python
{

PyTypeObject * getPyPythonFunctionType();

}
}

#endif
6 changes: 6 additions & 0 deletions src/pygeosx/pygeosx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "fileIO/python/PyHistoryCollectionType.hpp"
#include "fileIO/python/PyHistoryOutputType.hpp"
#include "fileIO/python/PyVTKOutputType.hpp"
#include "functions/python/PyPythonFunctionType.hpp"
#include "mainInterface/initialization.hpp"
#include "LvArray/src/python/PyArray.hpp"

Expand Down Expand Up @@ -430,6 +431,11 @@ PyInit_pygeosx()
return nullptr;
}

if( !LvArray::python::addTypeToModule( module, geos::python::getPyPythonFunctionType(), "PythonFunction" ) )
{
return nullptr;
}

// Add the LvArray submodule.
if( !LvArray::python::addPyLvArrayModule( module ) )
{
Expand Down