Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gradient related API #145

Merged
merged 33 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6e7a70b
Add write_block_vector_gradient_data
kursatyurt Jul 2, 2022
9e35847
Add gradient related API
kursatyurt Jul 2, 2022
9f02b68
Add rest of the API calls
kursatyurt Jul 2, 2022
bd7d031
Typo and indentation fixes
kursatyurt Jul 4, 2022
dc6237c
Change values to gradientValues
kursatyurt Jul 13, 2022
6ac64b8
Update cyprecice/cyprecice.pyx
kursatyurt Jul 13, 2022
76ec779
Add is_gradient_data_required method
kursatyurt Jul 13, 2022
7f021a3
Add write_tests
kursatyurt Jul 13, 2022
ed5de3d
Merge branch 'precice:develop' into gradient_API
kursatyurt Jul 13, 2022
5fd0259
Change doc of isGradientRequired
kursatyurt Jul 14, 2022
32b3144
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
d90ee95
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
89a6bca
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
b0af3f2
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
7d6bfef
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
6dba6be
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
fd805b4
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
ccf1b02
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
90fe22e
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
96a8b28
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
0f5339b
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
7668918
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
adcf87d
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
5e8626e
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
e810b15
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
e250476
Update cyprecice/cyprecice.pyx
kursatyurt Jul 14, 2022
dcf790f
Add asserttions to tests
kursatyurt Jul 14, 2022
2360179
Minor fixes
IshaanDesai Jul 15, 2022
56643f7
Change gradient tests to read
kursatyurt Jul 21, 2022
1a4e20f
Typo fixes
kursatyurt Jul 21, 2022
37e3f9a
Fixing test_write_block_scalar_gradient_data_single_float
IshaanDesai Jul 21, 2022
66e9339
Further smoothing the gradient data tests
IshaanDesai Jul 21, 2022
eaadfba
Merge branch 'precice:develop' into gradient_API
kursatyurt Aug 31, 2022
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
12 changes: 12 additions & 0 deletions cyprecice/SolverInterface.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ cdef extern from "precice/SolverInterface.hpp" namespace "precice":

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

# Gradient related API

bool isGradientDataRequired(int dataID) const;

void writeBlockVectorGradientData(int dataID, int size, const int* valueIndices, const double* gradientValues);

void writeScalarGradientData(int dataID, int valueIndex, const double* gradientValues);

void writeVectorGradientData(int dataID, int valueIndex, const double* gradientValues);

void writeBlockScalarGradientData(int dataID, int size, const int* valueIndices, const double* gradientValues);

# direct mesh access

void setMeshAccessRegion (const int meshID, const double* boundingBox) const
Expand Down
239 changes: 239 additions & 0 deletions cyprecice/cyprecice.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,245 @@ cdef class Interface:
self.thisptr.readScalarData (data_id, vertex_id, _value)
return _value

def write_block_vector_gradient_data (self, data_id, vertex_ids, gradientValues):
"""
Writes vector gradient data given as block. This function writes gradient values of specified vertices to a dataID.
Values are provided as a block of continuous memory. Values are stored in a numpy array [N x D] where N = number
IshaanDesai marked this conversation as resolved.
Show resolved Hide resolved
of vertices and D = number of gradient components.

Parameters
----------
data_id : int
Data ID to write to.
vertex_ids : array_like
Indices of the vertices.
gradientValues : array_like
Gradient values differentiated in the spacial direction (dx, dy) for 2D space, (dx, dy, dz) for 3D space
IshaanDesai marked this conversation as resolved.
Show resolved Hide resolved

Notes
-----
Previous calls:
Count of available elements at values matches the configured dimension
IshaanDesai marked this conversation as resolved.
Show resolved Hide resolved
Count of available elements at vertex_ids matches the given size
Initialize() has been called
Data with dataID has attribute hasGradient = true

Examples
--------
Write block gradient vector data for a 2D problem with 2 vertices:
>>> data_id = 1
>>> vertex_ids = [1, 2]
>>> gradientValues = np.array([[v1x_dx, v1y_dx, v1x_dy, v1y_dy], [v2x_dx, v2y_dx, v2x_dy, v2y_dy]])
>>> interface.write_block_vector_gradient_data(data_id, vertex_ids, gradientValues)

Write block vector data for a 3D (D=3) problem with 2 (N=2) vertices:
>>> data_id = 1
>>> vertex_ids = [1, 2]
>>> 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]])
>>> interface.write_block_vector_gradient_data(data_id, vertex_ids, gradientValues)
"""
check_array_like(vertex_ids, "vertex_ids", "write_block_vector_gradient_data")
check_array_like(gradientValues, "gradientValues", "write_block_vector_gradient_data")

if not isinstance(gradientValues, np.ndarray):
gradientValues = np.asarray(gradientValues)

if len(gradientValues) > 0:
size, dimensions = gradientValues.shape
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())
if len(gradientValues) == 0:
size = 0

cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32)
cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)

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())
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)

self.thisptr.writeBlockVectorGradientData (data_id, size, <const int*>_vertex_ids.data, <const double*>_gradientValues.data)

def write_scalar_gradient_data (self, data_id, vertex_id, gradientValues):
"""
Writes scalar gradient data to a vertex
This function writes the corresponding gradient matrix value of a specified vertex to a dataID.

The gradients need to be provided in the following format:

The 2D-format of gradientValues is (v_dx, v_dy) vector corresponding to the data block v = (v)
differentiated respectively in x-direction dx and y-direction dy

The 3D-format of gradientValues is (v_dx, v_dy, v_dz) vector
corresponding to the data block v = (v) differentiated respectively in spatial directions x-direction dx and y-direction dy and z-direction dz

Parameters
----------
data_id : int
ID to write to.
vertex_id : int
Index of the vertex.
gradientValue : array_like
A vector of the gradient values.

Notes
-----
Count of available elements at value matches the configured dimension
Vertex with dataID exists and contains data
Data with dataID has attribute hasGradient = true

Previous calls:
initialize() has been called

Examples
--------
Write scalar data for a 2D problem:
>>> data_id = 1
>>> vertex_id = 5
>>> gradientValue = [v5_dx, v5_dy]
>>> interface.write_scalar_gradient_data(data_id, vertex_id, gradientValue)
"""

check_array_like(gradientValues, "gradientValues", "write_scalar_gradient_data")

if not isinstance(gradientValues, np.ndarray):
gradientValues = np.asarray(gradientValues)

cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)

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())

self.thisptr.writeScalarGradientData(data_id, vertex_id, <const double*>_gradientValues.data)

def write_vector_gradient_data (self, data_id, vertex_id, gradientValues):
"""
Writes vector gradient data to a vertex
This function writes the corresponding gradient matrix value of a specified vertex to a dataID.

The gradients need to be provided in the following format:

The 2D-format of \p gradientValues is (vx_dx, vy_dx, vx_dy, vy_dy) vector corresponding to the data block v = (vx, vy)
differentiated respectively in x-direction dx and y-direction dy

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
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

Parameters
----------
data_id : int
ID to write to.
vertex_id : int
Index of the vertex.
gradientValue : array_like
A vector of the gradient values.

Notes
-----
Count of available elements at value matches the configured dimension
Vertex with dataID exists and contains data
Data with dataID has attribute hasGradient = true

Previous calls:
initialize() has been called

Examples
--------
Write scalar data for a 2D problem:
>>> data_id = 1
>>> vertex_id = 5
>>> gradientValue = [v5x_dx, v5y_dx, v5x_dy,v5y_dy]
>>> interface.write_vector_gradient_data(data_id, vertex_id, gradientValue)
"""

check_array_like(gradientValues, "gradientValues", "write_vector_gradient_data")

if not isinstance(gradientValues, np.ndarray):
gradientValues = np.asarray(gradientValues)

cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)

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())

self.thisptr.writeVectorGradientData(data_id, vertex_id, <const double*>_gradientValues.data)

def write_block_scalar_gradient_data (self, data_id, vertex_ids, gradientValues):
"""
Writes scalar gradient data given as block. This function writes values of specified vertices to a dataID.
Values are provided as a block of continuous memory. Values are stored in a numpy array [N x D] where N = number
of vertices and D = dimensions of geometry.

Parameters
----------
data_id : int
Data ID to write to.
vertex_ids : array_like
Indices of the vertices.
gradientValues : array_like
Gradient values differentiated in the spacial direction (dx, dy) for 2D space, (dx, dy, dz) for 3D space

Notes
-----
Previous calls:
Count of available elements at values matches the configured dimension
Count of available elements at vertex_ids matches the given size
Initialize() has been called
Data with dataID has attribute hasGradient = true

Examples
--------
Write block gradient scalar data for a 2D problem with 2 vertices:
>>> data_id = 1
>>> vertex_ids = [1, 2]
>>> gradientValues = np.array([[v1_dx, v1_dy], [v2_dx, v2_dy]])
>>> interface.write_block_scalar_gradient_data(data_id, vertex_ids, gradientValues)

Write block scalar data for a 3D (D=3) problem with 2 (N=2) vertices:
>>> data_id = 1
>>> vertex_ids = [1, 2]
>>> values = np.array([[v1_dx, v1_dy, v1x_dz], [v2_dx, v2_dy, v2_dz]])
>>> interface.write_block_scalar_gradient_data(data_id, vertex_ids, values)
"""
check_array_like(vertex_ids, "vertex_ids", "write_block_scalar_gradient_data")
check_array_like(gradientValues, "gradientValues", "write_block_sclar_gradient_data")

if not isinstance(gradientValues, np.ndarray):
gradientValues = np.asarray(gradientValues)

if len(gradientValues) > 0:
size, dimensions = gradientValues.shape
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())
if len(gradientValues) == 0:
size = 0

cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32)
cdef np.ndarray[double, ndim=1] _gradientValues = np.ascontiguousarray(gradientValues.flatten(), dtype=np.double)

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())
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)

self.thisptr.writeBlockScalarGradientData (data_id, size, <const int*>_vertex_ids.data, <const double*>_gradientValues.data)

def is_gradient_data_required(self,data_id):
"""
Checks if the given data set requires gradient data. We check if the data object has been intialized with the gradient flag.

Parameters
kursatyurt marked this conversation as resolved.
Show resolved Hide resolved
----------
data_id : int
Data ID to check.

Returns
-------
bool
True if gradient data is required for a dataID.

Examples
--------
Check if gradient data is required for a dataID:
>>> data_id = 1
>>> interface.is_gradient_data_required(data_id)
"""
return self.thisptr.isGradientDataRequired(data_id)


def set_mesh_access_region (self, mesh_id, bounding_box):
"""
This function is required if you don't want to use the mapping schemes in preCICE, but rather
Expand Down
52 changes: 51 additions & 1 deletion test/SolverInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,56 @@ void SolverInterface:: getMeshVerticesAndIDs
}
}

bool SolverInterface::isGradientDataRequired(int dataID) const
{
return 0;
}

void SolverInterface::writeBlockVectorGradientData(
int dataID,
int size,
const int *valueIndices,
const double *gradientValues)
{
fake_read_write_buffer.clear();
for (int i = 0; i < size * this->getDimensions() * this->getDimensions(); i++) {
fake_read_write_buffer.push_back(gradientValues[i]);
}
}

void SolverInterface::writeScalarGradientData(
int dataID,
int valueIndex,
const double *gradientValues)
{
fake_read_write_buffer.clear();
for (int i = 0; i < this->getDimensions(); i++) {
fake_read_write_buffer.push_back(gradientValues[i]);
}
}
void SolverInterface::writeBlockScalarGradientData(
int dataID,
int size,
const int *valueIndices,
const double *gradientValues)
{
fake_read_write_buffer.clear();
for (int i = 0; i < size * this->getDimensions(); i++) {
fake_read_write_buffer.push_back(gradientValues[i]);
}
}

void SolverInterface::writeVectorGradientData(
int dataID,
int valueIndex,
const double *gradientValues)
{
fake_read_write_buffer.clear();
for (int i = 0; i < this->getDimensions() * this->getDimensions(); i++) {
fake_read_write_buffer.push_back(gradientValues[i]);
}
}

std::string getVersionInformation()
{
std::string dummy ("dummy");
Expand Down Expand Up @@ -423,4 +473,4 @@ const std::string& actionReadIterationCheckpoint()

} // namespace precice, constants

} // namespace precice
} // namespace precice
Loading