Skip to content

Commit fcee5ff

Browse files
authored
Merge pull request #151 from precice/python-bindings-v2.5.0.1
Release v2.5.0.1
2 parents cff454d + f48b04d commit fcee5ff

6 files changed

Lines changed: 447 additions & 1 deletion

File tree

.github/workflows/pythonpublish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
cython
2525
packaging
2626
numpy
27+
pkgconfig
2728
- name: Build and publish
2829
env:
2930
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44

55
## latest
66

7+
## 2.5.0.1
8+
9+
* Add pkgconfig as dependency to the pythonpublish workflow https://github.com/precice/python-bindings/commit/200dc2aba160e18a7d1dae44ef3493d546e69eb9
10+
711
## 2.5.0.0
812

913
* Bindings now use pkgconfig to determine flags and link to preCICE. https://github.com/precice/python-bindings/pull/149

cyprecice/SolverInterface.pxd

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,18 @@ cdef extern from "precice/SolverInterface.hpp" namespace "precice":
101101

102102
void readScalarData (const int dataID, const int valueIndex, double& value) const
103103

104+
# Gradient related API
105+
106+
bool isGradientDataRequired(int dataID) const;
107+
108+
void writeBlockVectorGradientData(int dataID, int size, const int* valueIndices, const double* gradientValues);
109+
110+
void writeScalarGradientData(int dataID, int valueIndex, const double* gradientValues);
111+
112+
void writeVectorGradientData(int dataID, int valueIndex, const double* gradientValues);
113+
114+
void writeBlockScalarGradientData(int dataID, int size, const int* valueIndices, const double* gradientValues);
115+
104116
# direct mesh access
105117

106118
void setMeshAccessRegion (const int meshID, const double* boundingBox) const

cyprecice/cyprecice.pyx

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,245 @@ cdef class Interface:
12111211
self.thisptr.readScalarData (data_id, vertex_id, _value)
12121212
return _value
12131213

1214+
def write_block_vector_gradient_data (self, data_id, vertex_ids, gradientValues):
1215+
"""
1216+
Writes vector gradient data given as block. This function writes gradient values of specified vertices to a dataID.
1217+
Values are provided as a block of continuous memory. Values are stored in a numpy array [N x D] where N = number
1218+
of vertices and D = number of gradient components.
1219+
1220+
Parameters
1221+
----------
1222+
data_id : int
1223+
Data ID to write to.
1224+
vertex_ids : array_like
1225+
Indices of the vertices.
1226+
gradientValues : array_like
1227+
Gradient values differentiated in the spacial direction (dx, dy) for 2D space, (dx, dy, dz) for 3D space
1228+
1229+
Notes
1230+
-----
1231+
Previous calls:
1232+
Count of available elements at values matches the configured dimension
1233+
Count of available elements at vertex_ids matches the given size
1234+
Initialize() has been called
1235+
Data with dataID has attribute hasGradient = true
1236+
1237+
Examples
1238+
--------
1239+
Write block gradient vector data for a 2D problem with 2 vertices:
1240+
>>> data_id = 1
1241+
>>> vertex_ids = [1, 2]
1242+
>>> gradientValues = np.array([[v1x_dx, v1y_dx, v1x_dy, v1y_dy], [v2x_dx, v2y_dx, v2x_dy, v2y_dy]])
1243+
>>> interface.write_block_vector_gradient_data(data_id, vertex_ids, gradientValues)
1244+
1245+
Write block vector data for a 3D (D=3) problem with 2 (N=2) vertices:
1246+
>>> data_id = 1
1247+
>>> vertex_ids = [1, 2]
1248+
>>> gradientValues = np.array([[v1x_dx, v1y_dx, v1z_dx, v1x_dy, v1y_dy, v1z_dy, v1x_dz, v1y_dz, v1z_dz], [v2x_dx, v2y_dx, v2z_dx, v2x_dy, v2y_dy, v2z_dy, v2x_dz, v2y_dz, v2z_dz]])
1249+
>>> interface.write_block_vector_gradient_data(data_id, vertex_ids, gradientValues)
1250+
"""
1251+
check_array_like(vertex_ids, "vertex_ids", "write_block_vector_gradient_data")
1252+
check_array_like(gradientValues, "gradientValues", "write_block_vector_gradient_data")
1253+
1254+
if not isinstance(gradientValues, np.ndarray):
1255+
gradientValues = np.asarray(gradientValues)
1256+
1257+
if len(gradientValues) > 0:
1258+
size, dimensions = gradientValues.shape
1259+
assert dimensions == self.get_dimensions() * self.get_dimensions(), "Dimensions of vector data in write_block_vector_gradient_data does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_dimensions() * self.get_dimensions())
1260+
if len(gradientValues) == 0:
1261+
size = 0
1262+
1263+
cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32)
1264+
cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)
1265+
1266+
assert _gradientValues.size == size * self.get_dimensions() * self.get_dimensions(), "Dimension of vector gradient data provided in write_block_vector_gradient_data does not match problem definition. Check length of input data provided. Provided size: {}, expected size: {}".format(_gradientValues.size, size * self.get_dimensions() * self.get_dimensions())
1267+
assert _vertex_ids.size == size, "Vertex IDs are of incorrect length in write_block_vector_gradient_data. Check length of vertex ids input. Provided size: {}, expected size: {}".format(_vertex_ids.size, size)
1268+
1269+
self.thisptr.writeBlockVectorGradientData (data_id, size, <const int*>_vertex_ids.data, <const double*>_gradientValues.data)
1270+
1271+
def write_scalar_gradient_data (self, data_id, vertex_id, gradientValues):
1272+
"""
1273+
Writes scalar gradient data to a vertex
1274+
This function writes the corresponding gradient matrix value of a specified vertex to a dataID.
1275+
1276+
The gradients need to be provided in the following format:
1277+
1278+
The 2D-format of gradientValues is (v_dx, v_dy) vector corresponding to the data block v = (v)
1279+
differentiated respectively in x-direction dx and y-direction dy
1280+
1281+
The 3D-format of gradientValues is (v_dx, v_dy, v_dz) vector
1282+
corresponding to the data block v = (v) differentiated respectively in spatial directions x-direction dx and y-direction dy and z-direction dz
1283+
1284+
Parameters
1285+
----------
1286+
data_id : int
1287+
ID to write to.
1288+
vertex_id : int
1289+
Index of the vertex.
1290+
gradientValue : array_like
1291+
A vector of the gradient values.
1292+
1293+
Notes
1294+
-----
1295+
Count of available elements at value matches the configured dimension
1296+
Vertex with dataID exists and contains data
1297+
Data with dataID has attribute hasGradient = true
1298+
1299+
Previous calls:
1300+
initialize() has been called
1301+
1302+
Examples
1303+
--------
1304+
Write scalar data for a 2D problem:
1305+
>>> data_id = 1
1306+
>>> vertex_id = 5
1307+
>>> gradientValue = [v5_dx, v5_dy]
1308+
>>> interface.write_scalar_gradient_data(data_id, vertex_id, gradientValue)
1309+
"""
1310+
1311+
check_array_like(gradientValues, "gradientValues", "write_scalar_gradient_data")
1312+
1313+
if not isinstance(gradientValues, np.ndarray):
1314+
gradientValues = np.asarray(gradientValues)
1315+
1316+
cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)
1317+
1318+
assert _gradientValues.size == self.get_dimensions(), "Vector data provided for vertex {} in write_scalar_gradient_data does not match problem definition. Check length of input data provided. Provided size: {}, expected size: {}".format(_gradientValues.size, self.get_dimensions())
1319+
1320+
self.thisptr.writeScalarGradientData(data_id, vertex_id, <const double*>_gradientValues.data)
1321+
1322+
def write_vector_gradient_data (self, data_id, vertex_id, gradientValues):
1323+
"""
1324+
Writes vector gradient data to a vertex
1325+
This function writes the corresponding gradient matrix value of a specified vertex to a dataID.
1326+
1327+
The gradients need to be provided in the following format:
1328+
1329+
The 2D-format of \p gradientValues is (vx_dx, vy_dx, vx_dy, vy_dy) vector corresponding to the data block v = (vx, vy)
1330+
differentiated respectively in x-direction dx and y-direction dy
1331+
1332+
The 3D-format of \p gradientValues is (vx_dx, vy_dx, vz_dx, vx_dy, vy_dy, vz_dy, vx_dz, vy_dz, vz_dz) vector
1333+
corresponding to the data block v = (vx, vy, vz) differentiated respectively in spatial directions x-direction dx and y-direction dy and z-direction dz
1334+
1335+
Parameters
1336+
----------
1337+
data_id : int
1338+
ID to write to.
1339+
vertex_id : int
1340+
Index of the vertex.
1341+
gradientValue : array_like
1342+
A vector of the gradient values.
1343+
1344+
Notes
1345+
-----
1346+
Count of available elements at value matches the configured dimension
1347+
Vertex with dataID exists and contains data
1348+
Data with dataID has attribute hasGradient = true
1349+
1350+
Previous calls:
1351+
initialize() has been called
1352+
1353+
Examples
1354+
--------
1355+
Write scalar data for a 2D problem:
1356+
>>> data_id = 1
1357+
>>> vertex_id = 5
1358+
>>> gradientValue = [v5x_dx, v5y_dx, v5x_dy,v5y_dy]
1359+
>>> interface.write_vector_gradient_data(data_id, vertex_id, gradientValue)
1360+
"""
1361+
1362+
check_array_like(gradientValues, "gradientValues", "write_vector_gradient_data")
1363+
1364+
if not isinstance(gradientValues, np.ndarray):
1365+
gradientValues = np.asarray(gradientValues)
1366+
1367+
cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)
1368+
1369+
assert _gradientValues.size == self.get_dimensions() * self.get_dimensions(), "Dimensions of vector gradient data provided for vertex {} in write_vector_gradient_data does not match problem definition. Check length of input data provided. Provided size: {}, expected size: {}".format(_gradientValues.size, self.get_dimensions() * self.get_dimensions())
1370+
1371+
self.thisptr.writeVectorGradientData(data_id, vertex_id, <const double*>_gradientValues.data)
1372+
1373+
def write_block_scalar_gradient_data (self, data_id, vertex_ids, gradientValues):
1374+
"""
1375+
Writes scalar gradient data given as block. This function writes values of specified vertices to a dataID.
1376+
Values are provided as a block of continuous memory. Values are stored in a numpy array [N x D] where N = number
1377+
of vertices and D = dimensions of geometry.
1378+
1379+
Parameters
1380+
----------
1381+
data_id : int
1382+
Data ID to write to.
1383+
vertex_ids : array_like
1384+
Indices of the vertices.
1385+
gradientValues : array_like
1386+
Gradient values differentiated in the spacial direction (dx, dy) for 2D space, (dx, dy, dz) for 3D space
1387+
1388+
Notes
1389+
-----
1390+
Previous calls:
1391+
Count of available elements at values matches the configured dimension
1392+
Count of available elements at vertex_ids matches the given size
1393+
Initialize() has been called
1394+
Data with dataID has attribute hasGradient = true
1395+
1396+
Examples
1397+
--------
1398+
Write block gradient scalar data for a 2D problem with 2 vertices:
1399+
>>> data_id = 1
1400+
>>> vertex_ids = [1, 2]
1401+
>>> gradientValues = np.array([[v1_dx, v1_dy], [v2_dx, v2_dy]])
1402+
>>> interface.write_block_scalar_gradient_data(data_id, vertex_ids, gradientValues)
1403+
1404+
Write block scalar data for a 3D (D=3) problem with 2 (N=2) vertices:
1405+
>>> data_id = 1
1406+
>>> vertex_ids = [1, 2]
1407+
>>> values = np.array([[v1_dx, v1_dy, v1x_dz], [v2_dx, v2_dy, v2_dz]])
1408+
>>> interface.write_block_scalar_gradient_data(data_id, vertex_ids, values)
1409+
"""
1410+
check_array_like(vertex_ids, "vertex_ids", "write_block_scalar_gradient_data")
1411+
check_array_like(gradientValues, "gradientValues", "write_block_sclar_gradient_data")
1412+
1413+
if not isinstance(gradientValues, np.ndarray):
1414+
gradientValues = np.asarray(gradientValues)
1415+
1416+
if len(gradientValues) > 0:
1417+
size, dimensions = gradientValues.shape
1418+
assert dimensions == self.get_dimensions() , "Dimensions of scalar gradient data provided in write_block_scalar_gradient_data does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_dimensions())
1419+
if len(gradientValues) == 0:
1420+
size = 0
1421+
1422+
cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32)
1423+
cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)
1424+
1425+
assert _gradientValues.size == size * self.get_dimensions(), "Scalar gradient data is not provided for all vertices in write_block_scalar_gradient_data. Check length of input data provided. Provided size: {}, expected size: {}".format(_gradientValues.size, size * self.get_dimensions())
1426+
assert _vertex_ids.size == size, "Vertex IDs are of incorrect length in write_block_scalar_gradient_data. Check length of vertex ids input. Provided size: {}, expected size: {}".format(_vertex_ids.size, size)
1427+
1428+
self.thisptr.writeBlockScalarGradientData (data_id, size, <const int*>_vertex_ids.data, <const double*>_gradientValues.data)
1429+
1430+
def is_gradient_data_required(self,data_id):
1431+
"""
1432+
Checks if the given data set requires gradient data. We check if the data object has been intialized with the gradient flag.
1433+
1434+
Parameters
1435+
----------
1436+
data_id : int
1437+
Data ID to check.
1438+
1439+
Returns
1440+
-------
1441+
bool
1442+
True if gradient data is required for a dataID.
1443+
1444+
Examples
1445+
--------
1446+
Check if gradient data is required for a dataID:
1447+
>>> data_id = 1
1448+
>>> interface.is_gradient_data_required(data_id)
1449+
"""
1450+
return self.thisptr.isGradientDataRequired(data_id)
1451+
1452+
12141453
def set_mesh_access_region (self, mesh_id, bounding_box):
12151454
"""
12161455
This function is required if you don't want to use the mapping schemes in preCICE, but rather

test/SolverInterface.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,56 @@ void SolverInterface:: getMeshVerticesAndIDs
395395
}
396396
}
397397

398+
bool SolverInterface::isGradientDataRequired(int dataID) const
399+
{
400+
return 0;
401+
}
402+
403+
void SolverInterface::writeBlockVectorGradientData(
404+
int dataID,
405+
int size,
406+
const int *valueIndices,
407+
const double *gradientValues)
408+
{
409+
fake_read_write_buffer.clear();
410+
for (int i = 0; i < size * this->getDimensions() * this->getDimensions(); i++) {
411+
fake_read_write_buffer.push_back(gradientValues[i]);
412+
}
413+
}
414+
415+
void SolverInterface::writeScalarGradientData(
416+
int dataID,
417+
int valueIndex,
418+
const double *gradientValues)
419+
{
420+
fake_read_write_buffer.clear();
421+
for (int i = 0; i < this->getDimensions(); i++) {
422+
fake_read_write_buffer.push_back(gradientValues[i]);
423+
}
424+
}
425+
void SolverInterface::writeBlockScalarGradientData(
426+
int dataID,
427+
int size,
428+
const int *valueIndices,
429+
const double *gradientValues)
430+
{
431+
fake_read_write_buffer.clear();
432+
for (int i = 0; i < size * this->getDimensions(); i++) {
433+
fake_read_write_buffer.push_back(gradientValues[i]);
434+
}
435+
}
436+
437+
void SolverInterface::writeVectorGradientData(
438+
int dataID,
439+
int valueIndex,
440+
const double *gradientValues)
441+
{
442+
fake_read_write_buffer.clear();
443+
for (int i = 0; i < this->getDimensions() * this->getDimensions(); i++) {
444+
fake_read_write_buffer.push_back(gradientValues[i]);
445+
}
446+
}
447+
398448
std::string getVersionInformation()
399449
{
400450
std::string dummy ("dummy");
@@ -423,4 +473,4 @@ const std::string& actionReadIterationCheckpoint()
423473

424474
} // namespace precice, constants
425475

426-
} // namespace precice
476+
} // namespace precice

0 commit comments

Comments
 (0)