diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ff85c57c..2dbbf1a9 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -96,7 +96,7 @@ jobs: run: | git clone --branch develop https://github.com/precice/precice.git precice-core mkdir -p precice - cp precice-core/src/precice/SolverInterface.hpp precice/SolverInterface.hpp + cp precice-core/src/precice/Participant.hpp precice/Participant.hpp cp precice-core/src/precice/Tooling.hpp precice/Tooling.hpp cp precice-core/src/precice/Tooling.hpp precice/Tooling.cpp cd precice-core diff --git a/cyprecice/Participant.pxd b/cyprecice/Participant.pxd new file mode 100644 index 00000000..355237af --- /dev/null +++ b/cyprecice/Participant.pxd @@ -0,0 +1,92 @@ +from libcpp cimport bool +from libcpp.set cimport set +from libcpp.string cimport string +from libcpp.vector cimport vector + +cdef extern from "precice/Participant.hpp" namespace "precice": + cdef cppclass Participant: + # construction and configuration + + Participant (const string&, const string&, int, int) except + + + Participant (const string&, const string&, int, int, void*) except + + + void configure (const string&) + + # steering methods + + void initialize () + + void advance (double computedTimestepLength) + + void finalize() + + # status queries + + int getMeshDimensions(const string& meshName) const + + int getDataDimensions(const string& meshName, const string& dataName) const + + bool isCouplingOngoing() const + + bool isTimeWindowComplete() const + + double getMaxTimeStepSize() const + + bool requiresInitialData() + + bool requiresWritingCheckpoint() + + bool requiresReadingCheckpoint() + + # mesh access + + bool hasMesh (const string& meshName) const + + bool requiresMeshConnectivityFor (const string& meshName) const + + int setMeshVertex (const string& meshName, vector[double] position) + + int getMeshVertexSize (const string& meshName) const + + void setMeshVertices (const string& meshName, vector[double] positions, vector[int]& ids) + + void setMeshEdge (const string& meshName, int firstVertexID, int secondVertexID) + + void setMeshEdges (const string& meshName, vector[int] vertices) + + void setMeshTriangle (const string& meshName, int firstVertexID, int secondVertexID, int thirdVertexID) + + void setMeshTriangles (const string& meshName, vector[int] vertices) + + void setMeshQuad (const string& meshName, int firstVertexID, int secondVertexID, int thirdVertexID, int fourthVertexID) + + void setMeshQuads (const string& meshName, vector[int] vertices) + + void setMeshTetrahedron (const string& meshName, int firstVertexID, int secondVertexID, int thirdVertexID, int fourthVertexID) + + void setMeshTetrahedra (const string& meshName, vector[int] vertices) + + # data access + + bool hasData (const string& dataName, const string& meshName) const + + void writeData (const string& meshName, const string& dataName, vector[int] vertices, vector[double] values) + + void readData (const string& meshName, const string& dataName, vector[int] vertices, const double relativeReadTime, vector[double]& values) const + + # direct access + + void setMeshAccessRegion (const string& meshName, vector[double] boundingBox) const + + void getMeshVerticesAndIDs (const string& meshName, vector[int]& ids, vector[double]& coordinates) const + + # Gradient related API + + bool requiresGradientDataFor(const string& meshName, const string& dataName) const + + void writeGradientData(const string& meshName, const string& dataName, vector[int] vertices, vector[double] gradientValues) + + +cdef extern from "precice/Tooling.hpp" namespace "precice": + string getVersionInformation() diff --git a/cyprecice/SolverInterface.pxd b/cyprecice/SolverInterface.pxd deleted file mode 100644 index e5282f68..00000000 --- a/cyprecice/SolverInterface.pxd +++ /dev/null @@ -1,114 +0,0 @@ -from libcpp cimport bool -from libcpp.set cimport set -from libcpp.string cimport string - -cdef extern from "" namespace "std": - cdef cppclass string_view: - string_view() except + - string_view(const string&) except + # necessary to cast Python strings to string_view before handing over to C++ API - - -cdef extern from "precice/SolverInterface.hpp" namespace "precice": - cdef cppclass SolverInterface: - # construction and configuration - - SolverInterface (const string&, const string&, int, int) except + - - SolverInterface (const string&, const string&, int, int, void*) except + - - void configure (const string&) - - # steering methods - - double initialize () - - double advance (double computedTimestepLength) - - void finalize() - - # status queries - - int getDimensions() const - - bool isCouplingOngoing() const - - bool isTimeWindowComplete() const - - bool requiresInitialData() - - bool requiresReadingCheckpoint() - - bool requiresWritingCheckpoint() - - # mesh access - - bool hasMesh (const char* meshName) const - - bool requiresMeshConnectivityFor (const char* meshName) const - - int setMeshVertex (const char* meshName, const double* position) - - int getMeshVertexSize (const char* meshName) const - - void setMeshVertices (const char* meshName, int size, const double* positions, int* ids) - - void setMeshEdge (const char* meshName, int firstVertexID, int secondVertexID) - - void setMeshEdges (const char* meshName, int size, const int* vertices) - - void setMeshTriangle (const char* meshName, int firstVertexID, int secondVertexID, int thirdVertexID) - - void setMeshTriangles (const char* meshName, int size, const int* vertices) - - void setMeshQuad (const char* meshName, int firstVertexID, int secondVertexID, int thirdVertexID, int fourthVertexID) - - void setMeshQuads (const char* meshName, int size, const int* vertices) - - # data access - - bool hasData (const char* dataName, const char* meshName) const - - void writeBlockVectorData (const char* meshName, const char* dataName, const int size, const int* valueIndices, const double* values) - - void writeVectorData (const char* meshName, const char* dataName, const int valueIndex, const double* value) - - void writeBlockScalarData (const char* meshName, const char* dataName, const int size, const int* valueIndices, const double* values) - - void writeScalarData (const char* meshName, const char* dataName, const int valueIndex, const double value) - - void readBlockVectorData (const char* meshName, const char* dataName, const int size, const int* valueIndices, double* values) const - - void readBlockVectorData (const char* meshName, const char* dataName, const int size, const int* valueIndices, double relativeReadTime, double* values) const - - void readVectorData (const char* meshName, const char* dataName, const int valueIndex, double* value) const - - void readVectorData (const char* meshName, const char* dataName, const int valueIndex, double relativeReadTime, double* value) const - - void readBlockScalarData (const char* meshName, const char* dataName, const int size, const int* valueIndices, double* values) const - - void readBlockScalarData (const char* meshName, const char* dataName, const int size, const int* valueIndices, double relativeReadTime, double* values) const - - void readScalarData (const char* meshName, const char* dataName, const int valueIndex, double& value) const - - void readScalarData (const char* meshName, const char* dataName, const int valueIndex, double relativeReadTime, double& value) const - - # Gradient related API - - bool requiresGradientDataFor(const char* meshName, const char* dataName) const - - void writeBlockVectorGradientData(const char* meshName, const char* dataName, int size, const int* valueIndices, const double* gradientValues) - - void writeScalarGradientData(const char* meshName, const char* dataName, int valueIndex, const double* gradientValues) - - void writeVectorGradientData(const char* meshName, const char* dataName, int valueIndex, const double* gradientValues) - - void writeBlockScalarGradientData(const char* meshName, const char* dataName, int size, const int* valueIndices, const double* gradientValues) - - # direct mesh access - - void setMeshAccessRegion (const char* meshName, const double* boundingBox) const - - void getMeshVerticesAndIDs (const char* meshName, const int size, int* ids, double* coordinates) const - -cdef extern from "precice/Tooling.hpp" namespace "precice": - string getVersionInformation() diff --git a/cyprecice/cyprecice.pxd b/cyprecice/cyprecice.pxd index 0e6953db..32e819e4 100644 --- a/cyprecice/cyprecice.pxd +++ b/cyprecice/cyprecice.pxd @@ -5,10 +5,10 @@ The python module precice offers python language bindings to the C++ coupling li cimport numpy as np cimport cython -cimport SolverInterface +cimport Participant as CppParticipant from cpython.version cimport PY_MAJOR_VERSION # important for determining python version in order to properly normalize string input. See http://docs.cython.org/en/latest/src/tutorial/strings.html#general-notes-about-c-strings and https://github.com/precice/precice/issues/68 . @cython.embedsignature(True) -cdef class Interface: - cdef SolverInterface.SolverInterface *thisptr # hold a C++ instance being wrapped +cdef class Participant: + cdef CppParticipant.Participant *thisptr # hold a C++ instance being wrapped diff --git a/cyprecice/cyprecice.pyx b/cyprecice/cyprecice.pyx index 52289a5f..0eaf1cb0 100644 --- a/cyprecice/cyprecice.pyx +++ b/cyprecice/cyprecice.pyx @@ -10,14 +10,10 @@ import numpy as np from mpi4py import MPI import warnings from libcpp.string cimport string +from libcpp.vector cimport vector from cpython.version cimport PY_MAJOR_VERSION # important for determining python version in order to properly normalize string input. See http://docs.cython.org/en/latest/src/tutorial/strings.html#general-notes-about-c-strings and https://github.com/precice/precice/issues/68 . -cdef extern from "" namespace "std": - cdef cppclass string_view: - string_view() except + - string_view(const string&) except + # necessary to cast Python strings to string_view before handing over to C++ API - cdef bytes convert(s): """ source code from http://docs.cython.org/en/latest/src/tutorial/strings.html#general-notes-about-c-strings @@ -38,15 +34,14 @@ def check_array_like(argument, argument_name, function_name): raise TypeError("{} requires array_like input for {}, but was provided the following input type: {}".format( function_name, argument_name, type(argument))) from None -cdef class Interface: +cdef class Participant: """ Main Application Programming Interface of preCICE. To adapt a solver to preCICE, follow the following main structure: - - Create an object of SolverInterface with Interface() - - Configure the object with Interface::configure() - - Initialize preCICE with Interface::initialize() - - Advance to the next (time)step with Interface::advance() - - Finalize preCICE with Interface::finalize() + - Create an object of Participant with Participant() + - Initialize preCICE with Participant::initialize() + - Advance to the next (time)step with Participant::advance() + - Finalize preCICE with Participant::finalize() - We use solver, simulation code, and participant as synonyms. - The preferred name in the documentation is participant. """ @@ -54,7 +49,7 @@ cdef class Interface: # fake __init__ needed to display docstring for __cinit__ (see https://stackoverflow.com/a/42733794/5158031) def __init__(self, solver_name, configuration_file_name, solver_process_index, solver_process_size, communicator=None): """ - Constructor of Interface class. + Constructor of Participant class. Parameters ---------- @@ -71,12 +66,12 @@ cdef class Interface: Returns ------- - SolverInterface : object - Object pointing to the defined coupling interface + Participant : object + Object pointing to the defined participant Example ------- - >>> interface = precice.Interface("SolverOne", "precice-config.xml", 0, 1) + >>> participant = precice.Participant("SolverOne", "precice-config.xml", 0, 1) preCICE: This is preCICE version X.X.X preCICE: Revision info: vX.X.X-X-XXXXXXXXX preCICE: Configuring preCICE with configuration: "precice-config.xml" @@ -88,17 +83,18 @@ cdef class Interface: cdef void* communicator_ptr if communicator: communicator_ptr = communicator - self.thisptr = new SolverInterface.SolverInterface (convert(solver_name), convert(configuration_file_name), solver_process_index, solver_process_size, communicator_ptr) + self.thisptr = new CppParticipant.Participant (convert(solver_name), convert(configuration_file_name), solver_process_index, solver_process_size, communicator_ptr) else: - self.thisptr = new SolverInterface.SolverInterface (convert(solver_name), convert(configuration_file_name), solver_process_index, solver_process_size) + self.thisptr = new CppParticipant.Participant (convert(solver_name), convert(configuration_file_name), solver_process_index, solver_process_size) pass def __dealloc__ (self): """ - Destructor of Interface class + Destructor of Participant class """ del self.thisptr + # steering methods def initialize (self): @@ -118,7 +114,7 @@ cdef class Interface: max_timestep : double Maximum length of first timestep to be computed by the solver. """ - return self.thisptr.initialize () + self.thisptr.initialize () def advance (self, double computed_timestep_length): @@ -130,11 +126,6 @@ cdef class Interface: computed_timestep_length : double Length of timestep used by the solver. - Returns - ------- - max_timestep : double - Maximum length of next timestep to be computed by solver. - Notes ----- Previous calls: @@ -151,7 +142,7 @@ cdef class Interface: [Second Participant] Configured post processing schemes are applied. Meshes with data are exported to files if configured. """ - return self.thisptr.advance (computed_timestep_length) + self.thisptr.advance (computed_timestep_length) def finalize (self): @@ -169,19 +160,45 @@ cdef class Interface: """ self.thisptr.finalize () + # status queries - def get_dimensions (self): + def get_mesh_dimensions (self, mesh_name): """ - Returns the number of spatial dimensions configured. Currently, two and three dimensional problems - can be solved using preCICE. The dimension is specified in the XML configuration. + Returns the spatial dimensionality of the given mesh. + + Parameters + ---------- + mesh_name : string + Name of the mesh. Returns ------- dimension : int - The configured dimension. + The dimensions of the given mesh. + """ + + return self.thisptr.getMeshDimensions (convert(mesh_name)) + + + def get_data_dimensions (self, mesh_name, data_name): """ - return self.thisptr.getDimensions () + Returns the spatial dimensionality of the given data on the given mesh. + + Parameters + ---------- + mesh_name : string + Name of the mesh. + data_name : string + Name of the data. + + Returns + ------- + dimension : int + The dimensions of the given data. + """ + + return self.thisptr.getDataDimensions (convert(mesh_name), convert(data_name)) def is_coupling_ongoing (self): @@ -224,6 +241,27 @@ cdef class Interface: """ return self.thisptr.isTimeWindowComplete () + + def get_max_time_step_size (self): + """ + Get the maximum allowed time step size of the current window. + + Allows the user to query the maximum allowed time step size in the current window. + This should be used to compute the actual time step that the solver uses. + + Returns + ------- + tag : double + Maximum size of time step to be computed by solver. + + Notes + ----- + Previous calls: + initialize() has been called successfully. + """ + return self.thisptr.getMaxTimeStepSize () + + def requires_initial_data (self): """ Checks if the participant is required to provide initial data. @@ -262,7 +300,7 @@ cdef class Interface: def requires_reading_checkpoint (self): """ Checks if the participant is required to read an iteration checkpoint. - + If true, the participant is required to read an iteration checkpoint before calling advance(). @@ -294,15 +332,12 @@ cdef class Interface: tag : bool Returns true is the mesh is used. """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() + return self.thisptr.hasMesh (convert(mesh_name)) - return self.thisptr.hasMesh ( mesh_name_py_bytes) - - def get_mesh_handle(self, mesh_name): + def requires_mesh_connectivity_for (self, mesh_name): """ - Returns a handle to a created mesh. - WARNING: This function is not yet available for the Python bindings + Checks if the given mesh requires connectivity. Parameters ---------- @@ -311,10 +346,10 @@ cdef class Interface: Returns ------- - tag : object - Handle to the mesh. + tag : bool + True if mesh connectivity is required. """ - raise Exception("The API method get_mesh_handle is not yet available for the Python bindings.") + return self.thisptr.requiresMeshConnectivityFor(convert(mesh_name)) def set_mesh_vertex(self, mesh_name, position): @@ -342,17 +377,17 @@ cdef class Interface: if len(position) > 0: dimensions = len(position) - assert dimensions == self.get_dimensions(), "Dimensions of vertex coordinate in set_mesh_vertex does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_dimensions()) + assert dimensions == self.get_mesh_dimensions(mesh_name), "Dimensions of vertex coordinate in set_mesh_vertex does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_mesh_dimensions(mesh_name)) elif len(position) == 0: - dimensions = self.get_dimensions() + dimensions = self.get_mesh_dimensions(mesh_name) - cdef np.ndarray[double, ndim=1] _position = np.ascontiguousarray(position, dtype=np.double) + cdef vector[double] cpp_position = position - cdef bytes mesh_name_py_bytes = mesh_name.encode() + vertex_id = self.thisptr.setMeshVertex(convert(mesh_name), cpp_position) - vertex_id = self.thisptr.setMeshVertex( mesh_name_py_bytes, _position.data) return vertex_id + def get_mesh_vertex_size (self, mesh_name): """ Returns the number of vertices of a mesh @@ -367,9 +402,9 @@ cdef class Interface: sum : int Number of vertices of the mesh. """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() - return self.thisptr.getMeshVertexSize( mesh_name_py_bytes) + return self.thisptr.getMeshVertexSize(convert(mesh_name)) + def set_mesh_vertices (self, mesh_name, positions): """ @@ -403,7 +438,7 @@ cdef class Interface: >>> positions.shape (5, 2) >>> mesh_name = "MeshOne" - >>> vertex_ids = interface.set_mesh_vertices(mesh_name, positions) + >>> vertex_ids = participant.set_mesh_vertices(mesh_name, positions) >>> vertex_ids.shape (5,) @@ -413,7 +448,7 @@ cdef class Interface: >>> positions.shape (5, 3) >>> mesh_name = "MeshOne" - >>> vertex_ids = interface.set_mesh_vertices(mesh_name, positions) + >>> vertex_ids = participant.set_mesh_vertices(mesh_name, positions) >>> vertex_ids.shape (5,) """ @@ -424,19 +459,20 @@ cdef class Interface: if len(positions) > 0: size, dimensions = positions.shape - assert dimensions == self.get_dimensions(), "Dimensions of vertex coordinates in set_mesh_vertices does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_dimensions()) + assert dimensions == self.get_mesh_dimensions(mesh_name), "Dimensions of vertex coordinates in set_mesh_vertices does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_mesh_dimensions(mesh_name)) elif len(positions) == 0: - size = positions.shape[0] - dimensions = self.get_dimensions() + size = 0 + dimensions = self.get_mesh_dimensions(mesh_name) + + cdef vector[double] cpp_positions = positions.flatten() + cdef vector[int] cpp_ids = [-1 for _ in range(size)] + + self.thisptr.setMeshVertices (convert(mesh_name), cpp_positions, cpp_ids) - cdef np.ndarray[double, ndim=1] _positions = np.ascontiguousarray(positions.flatten(), dtype=np.double) - cdef np.ndarray[int, ndim=1] vertex_ids = np.empty(size, dtype=np.int32) + cdef np.ndarray[int, ndim=1] np_ids = np.array(cpp_ids, dtype=np.int32) - cdef bytes mesh_name_py_bytes = mesh_name.encode() - #cdef str mesh_name_str = mesh_name.encode() + return np_ids - self.thisptr.setMeshVertices ( mesh_name_py_bytes, size, _positions.data, vertex_ids.data) - return vertex_ids def set_mesh_edge (self, mesh_name, first_vertex_id, second_vertex_id): """ @@ -461,9 +497,9 @@ cdef class Interface: Previous calls: vertices with firstVertexID and secondVertexID were added to the mesh with name mesh_name """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() - self.thisptr.setMeshEdge ( mesh_name_py_bytes, first_vertex_id, second_vertex_id) + self.thisptr.setMeshEdge (convert(mesh_name), first_vertex_id, second_vertex_id) + def set_mesh_edges (self, mesh_name, vertices): """ @@ -484,7 +520,7 @@ cdef class Interface: >>> vertices = np.array([[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]) >>> vertices.shape (6, 2) - >>> interface.set_mesh_edges(mesh_name, vertices) + >>> participant.set_mesh_edges(mesh_name, vertices) """ check_array_like(vertices, "vertices", "set_mesh_edges") @@ -492,17 +528,15 @@ cdef class Interface: vertices = np.asarray(vertices) if len(vertices) > 0: - size, n = vertices.shape + _, n = vertices.shape assert n == 2, "Provided vertices are not of a [N x 2] format, but instead of a [N x {}]".format(n) elif len(vertices) == 0: - size = vertices.shape[0] - dimensions = self.get_dimensions() + dimensions = self.get_mesh_dimensions(mesh_name) - cdef np.ndarray[double, ndim=1] _vertices = np.ascontiguousarray(vertices.flatten(), dtype=np.int) + cdef vector[int] cpp_vertices = vertices.flatten() - cdef bytes mesh_name_py_bytes = mesh_name.encode() + self.thisptr.setMeshEdges (convert(mesh_name), cpp_vertices) - self.thisptr.setMeshEdges ( mesh_name_py_bytes, size, _vertices.data) def set_mesh_triangle (self, mesh_name, first_vertex_id, second_vertex_id, third_vertex_id): """ @@ -524,9 +558,9 @@ cdef class Interface: Previous calls: vertices with first_vertex_id, second_vertex_id, and third_vertex_id were added to the mesh with the name mesh_name """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() - self.thisptr.setMeshTriangle ( mesh_name_py_bytes, first_vertex_id, second_vertex_id, third_vertex_id) + self.thisptr.setMeshTriangle (convert(mesh_name), first_vertex_id, second_vertex_id, third_vertex_id) + def set_mesh_triangles (self, mesh_name, vertices): """ @@ -535,7 +569,7 @@ cdef class Interface: Parameters ---------- mesh_name : str - Name of the mesh to add the vertices to. + Name of the mesh to add the triangles to. vertices : array_like The IDs of the vertices in a numpy array [N x 3] where N = number of triangles and D = dimensions of geometry. @@ -547,7 +581,7 @@ cdef class Interface: >>> vertices = np.array([[1, 2, 3], [1, 3, 4], [1, 2, 4], [1, 3, 4]]) >>> vertices.shape (4, 2) - >>> interface.set_mesh_triangles(mesh_name, vertices) + >>> participant.set_mesh_triangles(mesh_name, vertices) """ check_array_like(vertices, "vertices", "set_mesh_triangles") @@ -555,17 +589,15 @@ cdef class Interface: vertices = np.asarray(vertices) if len(vertices) > 0: - size, n = vertices.shape - assert n == 3, "Provided vertices are not of a [N x 3] format, but instead of a [N x {}]".format(n) + _, n = vertices.shape + assert n == self.get_mesh_dimensions(mesh_name), "Provided vertices are not of a [N x {}] format, but instead of a [N x {}]".format(self.get_mesh_dimensions(mesh_name), n) elif len(vertices) == 0: - size = vertices.shape[0] - dimensions = self.get_dimensions() + dimensions = self.get_mesh_dimensions(mesh_name) - cdef np.ndarray[double, ndim=1] _vertices = np.ascontiguousarray(vertices.flatten(), dtype=np.int) + cdef vector[int] cpp_vertices = vertices.flatten() + + self.thisptr.setMeshTriangles (convert(mesh_name), cpp_vertices) - cdef bytes mesh_name_py_bytes = mesh_name.encode() - - self.thisptr.setMeshTriangles ( mesh_name_py_bytes, size, _vertices.data) def set_mesh_quad (self, mesh_name, first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id): """ @@ -574,7 +606,7 @@ cdef class Interface: Parameters ---------- mesh_name : str - Name of the mesh to add the Quad to. + Name of the mesh to add the quad to. first_vertex_id : int ID of the first vertex of the quad. second_vertex_id : int @@ -590,9 +622,9 @@ cdef class Interface: vertices with first_vertex_id, second_vertex_id, third_vertex_id, and fourth_vertex_id were added to the mesh with the name mesh_name """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() - - self.thisptr.setMeshQuad ( mesh_name_py_bytes, first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id) + + self.thisptr.setMeshQuad (convert(mesh_name), first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id) + def set_mesh_quads (self, mesh_name, vertices): """ @@ -601,7 +633,7 @@ cdef class Interface: Parameters ---------- mesh_name : str - Name of the mesh to add the vertices to. + Name of the mesh to add the quads to. vertices : array_like The IDs of the vertices in a numpy array [N x 4] where N = number of quads and D = dimensions of geometry. @@ -613,7 +645,7 @@ cdef class Interface: >>> vertices = np.array([[1, 2, 3, 4]]) >>> vertices.shape (1, 2) - >>> interface.set_mesh_quads(mesh_name, vertices) + >>> participant.set_mesh_quads(mesh_name, vertices) """ check_array_like(vertices, "vertices", "set_mesh_quads") @@ -621,36 +653,80 @@ cdef class Interface: vertices = np.asarray(vertices) if len(vertices) > 0: - size, n = vertices.shape + _, n = vertices.shape assert n == 4, "Provided vertices are not of a [N x 4] format, but instead of a [N x {}]".format(n) elif len(vertices) == 0: - size = vertices.shape[0] - dimensions = self.get_dimensions() + dimensions = self.get_mesh_dimensions(mesh_name) - cdef np.ndarray[double, ndim=1] _vertices = np.ascontiguousarray(vertices.flatten(), dtype=np.int) + cdef vector[int] cpp_vertices = vertices.flatten() - cdef bytes mesh_name_py_bytes = mesh_name.encode() + self.thisptr.setMeshQuads (convert(mesh_name), cpp_vertices) - self.thisptr.setMeshQuads ( mesh_name_py_bytes, size, _vertices.data) - # data access + def set_mesh_tetrahedron (self, mesh_name, first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id): + """ + Sets a mesh tetrahedron from vertex IDs. - def requires_mesh_connectivity_for (self, mesh_name): + Parameters + ---------- + mesh_name : str + Name of the mesh to add the tetrahedron to. + first_vertex_id : int + ID of the first vertex of the tetrahedron. + second_vertex_id : int + ID of the second vertex of the tetrahedron. + third_vertex_id : int + ID of the third vertex of the tetrahedron. + fourth_vertex_id : int + ID of the third vertex of the tetrahedron. + + Notes + ----- + Previous calls: + vertices with first_vertex_id, second_vertex_id, third_vertex_id, and fourth_vertex_id were added + to the mesh with the name mesh_name """ - Checks if the given mesh requires connectivity. + + self.thisptr.setMeshTetrahedron (convert(mesh_name), first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id) + + + def set_mesh_tetrahedra (self, mesh_name, vertices): + """ + Creates multiple mesh tetdrahedrons Parameters ---------- mesh_name : str - ID of the associated mesh. + Name of the mesh to add the tetrahedrons to. + vertices : array_like + The IDs of the vertices in a numpy array [N x 4] where + N = number of quads and D = dimensions of geometry. - Returns - ------- - tag : bool - True if mesh connectivity is required. + Examples + -------- + Set mesh tetrahedrons for a problem with 4 mesh vertices. + + >>> vertices = np.array([[1, 2, 3, 4]]) + >>> vertices.shape + (1, 2) + >>> participant.set_mesh_tetradehra(mesh_name, vertices) """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() - return self.thisptr.requiresMeshConnectivityFor( mesh_name_py_bytes) + check_array_like(vertices, "vertices", "set_mesh_tetrahedra") + + if not isinstance(vertices, np.ndarray): + vertices = np.asarray(vertices) + + if len(vertices) > 0: + _, n = vertices.shape + assert n == 4, "Provided vertices are not of a [N x 4] format, but instead of a [N x {}]".format(n) + elif len(vertices) == 0: + dimensions = self.get_mesh_dimensions(mesh_name) + + cdef vector[int] cpp_vertices = vertices.flatten() + + self.thisptr.setMeshTetrahedra (convert(mesh_name), cpp_vertices) + + # data access def has_data (self, data_name, mesh_name): """ @@ -668,15 +744,14 @@ cdef class Interface: tag : bool True if the mesh is already used. """ - cdef bytes data_name_py_bytes = data_name.encode() - cdef bytes mesh_name_py_bytes = mesh_name.encode() - return self.thisptr.hasData( data_name_py_bytes, mesh_name_py_bytes) + return self.thisptr.hasData(convert(data_name), convert(mesh_name)) + - def write_block_vector_data (self, mesh_name, data_name, vertex_ids, values): + def write_data (self, mesh_name, data_name, vertex_ids, values): """ - Writes vector 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 + This function writes values of specified vertices to data of a mesh. + Values are provided as a block of continuous memory defined by values. Values are stored in a numpy array [N x D] where N = number of vertices and D = dimensions of geometry. + The order of the provided data follows the order specified by vertices. Parameters ---------- @@ -687,7 +762,7 @@ cdef class Interface: vertex_ids : array_like Indices of the vertices. values : array_like - Vector values of data + Values of data Notes ----- @@ -698,186 +773,55 @@ cdef class Interface: Examples -------- - Write block vector data for a 2D problem with 5 vertices: + Write scalar data for a 2D problem with 5 vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" >>> vertex_ids = [1, 2, 3, 4, 5] - >>> values = np.array([[v1_x, v1_y], [v2_x, v2_y], [v3_x, v3_y], [v4_x, v4_y], [v5_x, v5_y]]) - >>> interface.write_block_vector_data(mesh_name, data_name, vertex_ids, values) - - Write block vector data for a 3D (D=3) problem with 5 (N=5) vertices: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_ids = [1, 2, 3, 4, 5] - >>> values = np.array([[v1_x, v1_y, v1_z], [v2_x, v2_y, v2_z], [v3_x, v3_y, v3_z], [v4_x, v4_y, v4_z], [v5_x, v5_y, v5_z]]) - >>> interface.write_block_vector_data(mesh_name, data_name, vertex_ids, values) - """ - check_array_like(vertex_ids, "vertex_ids", "write_block_vector_data") - check_array_like(values, "values", "write_block_vector_data") - - if not isinstance(values, np.ndarray): - values = np.asarray(values) - - if len(values) > 0: - size, dimensions = values.shape - assert dimensions == self.get_dimensions(), "Dimensions of vector data in write_block_vector_data does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_dimensions()) - if len(values) == 0: - size = 0 - - cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32) - cdef np.ndarray[double, ndim=1] _values = np.ascontiguousarray(values.flatten(), dtype=np.double) - - assert _values.size == size * self.get_dimensions(), "Vector data is not provided for all vertices in write_block_vector_data. Check length of input data provided. Provided size: {}, expected size: {}".format(_values.size, size * self.get_dimensions()) - assert _vertex_ids.size == size, "Vertex IDs are of incorrect length in write_block_vector_data. Check length of vertex ids input. Provided size: {}, expected size: {}".format(_vertex_ids.size, size) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - self.thisptr.writeBlockVectorData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, _values.data) - - def write_vector_data (self, mesh_name, data_name, vertex_id, value): - """ - Writes vector data to a vertex. This function writes a value of a specified vertex to a dataID. - Values are provided as a block of continuous memory. - The 2D-format of value is a numpy array of shape 2 - The 3D-format of value is a numpy array of shape 3 - - Parameters - ---------- - mesh_name : str - Name of the mesh to write to. - data_name : str - ID to write to. - vertex_id : int - Index of the vertex. - value : array_like - Single vector value - - Notes - ----- - Previous calls: - count of available elements at value matches the configured dimension - initialize() has been called + >>> values = np.array([v1, v2, v3, v4, v5]) + >>> participant.write_data(mesh_name, data_name, vertex_ids, values) - Examples - -------- Write vector data for a 2D problem with 5 vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> value = np.array([v5_x, v5_y]) - >>> interface.write_vector_data(mesh_name, data_name, vertex_id, value) + >>> vertex_ids = [1, 2, 3, 4, 5] + >>> values = np.array([[v1_x, v1_y], [v2_x, v2_y], [v3_x, v3_y], [v4_x, v4_y], [v5_x, v5_y]]) + >>> participant.write_data(mesh_name, data_name, vertex_ids, values) Write vector data for a 3D (D=3) problem with 5 (N=5) vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> value = np.array([v5_x, v5_y, v5_z]) - >>> interface.write_vector_data(mesh_name, data_name, vertex_id, value) - """ - check_array_like(value, "value", "write_vector_data") - assert len(value) > 0, "Input vector data is empty in write_vector_data" - - dimensions = len(value) - - assert dimensions == self.get_dimensions(), "Dimensions of vector data in write_vector_data does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_dimensions()) - - cdef np.ndarray[np.double_t, ndim=1] _value = np.ascontiguousarray(value, dtype=np.double) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - self.thisptr.writeVectorData ( mesh_name_py_bytes, data_name_py_bytes, vertex_id, _value.data) - - def write_block_scalar_data (self, mesh_name, data_name, vertex_ids, values): - """ - Writes scalar data given as a block. This function writes values of specified vertices to a dataID. - - Parameters - ---------- - mesh_name : str - Name of the mesh to write to. - data_name : str - ID to write to. - vertex_ids : array_like - Indices of the vertices. - values : array_like - Values to be written - - Notes - ----- - Previous calls: - count of available elements at values matches the given size - count of available elements at vertex_ids matches the given size - initialize() has been called - - Examples - -------- - Write block scalar data for a 2D and 3D problem with 5 (N=5) vertices: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" >>> vertex_ids = [1, 2, 3, 4, 5] - >>> values = np.array([v1, v2, v3, v4, v5]) - >>> interface.write_block_scalar_data(mesh_name, data_name, vertex_ids, values) + >>> values = np.array([[v1_x, v1_y, v1_z], [v2_x, v2_y, v2_z], [v3_x, v3_y, v3_z], [v4_x, v4_y, v4_z], [v5_x, v5_y, v5_z]]) + >>> participant.write_data(mesh_name, data_name, vertex_ids, values) """ - check_array_like(vertex_ids, "vertex_ids", "write_block_scalar_data") - check_array_like(values, "values", "write_block_scalar_data") + check_array_like(vertex_ids, "vertex_ids", "write_data") + check_array_like(values, "values", "write_data") + + if not isinstance(values, np.ndarray): + values = np.asarray(values) - if len(values) > 0: - assert(len(vertex_ids) == len(values)) - size = len(vertex_ids) if len(values) == 0: size = 0 + elif self.get_data_dimensions(mesh_name, data_name) == 1: + size = values.flatten().shape[0] + dimensions = 1 + else: + assert len(values.shape) == 2, "Vector valued data has to be provided as a numpy array of shape [N x D] where N = number of vertices and D = number of dimensions." + size, dimensions = values.shape - cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32) - cdef np.ndarray[double, ndim=1] _values = np.ascontiguousarray(values, dtype=np.double) + assert dimensions == self.get_data_dimensions(mesh_name, data_name), "Dimensions of vector data in write_data do not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_data_dimensions(mesh_name, data_name)) - assert _values.size == size, "Scalar data is not provided for all vertices in write_block_scalar_data. Check size of input data provided. Provided size: {}, expected size: {}".format(_values.size, size) - assert _vertex_ids.size == size, "Vertex IDs are of incorrect length in write_block_scalar_data. Check size of vertex ids input. Provided size: {}, expected size: {}".format(_vertex_ids.size, size) + assert len(vertex_ids) == size, "Vertex IDs are of incorrect length in write_data. Check length of vertex ids input. Provided size: {}, expected size: {}".format(vertex_ids.size, size) - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() + cdef vector[int] cpp_ids = vertex_ids + cdef vector[double] cpp_values = values.flatten() - self.thisptr.writeBlockScalarData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, _values.data) + self.thisptr.writeData (convert(mesh_name), convert(data_name), cpp_ids, cpp_values) - def write_scalar_data (self, mesh_name, data_name, vertex_id, double value): - """ - Writes scalar data to a vertex - This function writes a value of a specified vertex to a dataID. - Parameters - ---------- - mesh_name : str - Name of the mesh to write to. - data_name : str - ID to write to. - vertex_id : int - Index of the vertex. - value : double - The value to write. - - Notes - ----- - Previous calls: - initialize() has been called - - Examples - -------- - Write scalar data for a 2D or 3D problem with 5 vertices: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> value = v5 - >>> interface.write_scalar_data(mesh_name, data_name, vertex_id, value) + def read_data (self, mesh_name, data_name, vertex_ids, relative_read_time): """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - self.thisptr.writeScalarData ( mesh_name_py_bytes, data_name_py_bytes, vertex_id, value) - - def read_block_vector_data (self, mesh_name, data_name, vertex_ids, relative_read_time=None): - """ - Reads vector data into a provided block. This function reads values of specified vertices + Reads data into a provided block. This function reads values of specified vertices from a dataID. Values are read into a block of continuous memory. Parameters @@ -905,202 +849,60 @@ cdef class Interface: Examples -------- - Read block vector data for a 2D problem with 5 vertices: + Read scalar data for a 2D problem with 5 vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" >>> vertex_ids = [1, 2, 3, 4, 5] - >>> values = read_block_vector_data(mesh_name, data_name, vertex_ids) + >>> values = read_data(mesh_name, data_name, vertex_ids) >>> values.shape - >>> (5, 2) + >>> (5, ) - Read block vector data for a 3D system with 5 vertices: + Read vector data for a 2D problem with 5 vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" >>> vertex_ids = [1, 2, 3, 4, 5] - >>> values = read_block_vector_data(mesh_name, data_name, vertex_ids) + >>> values = read_data(mesh_name, data_name, vertex_ids) >>> values.shape - >>> (5, 3) - """ - check_array_like(vertex_ids, "vertex_ids", "read_block_vector_data") - - cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32) - size = _vertex_ids.size - dimensions = self.get_dimensions() - cdef np.ndarray[np.double_t, ndim=1] _values = np.empty(size * dimensions, dtype=np.double) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - #cdef str mesh_name_str = mesh_name.encode() - #cdef str data_name_str = data_name.encode() - - if relative_read_time is None: - self.thisptr.readBlockVectorData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, _values.data) - else: - self.thisptr.readBlockVectorData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, relative_read_time, _values.data) - return _values.reshape((size, dimensions)) - - def read_vector_data (self, mesh_name, data_name, vertex_id, relative_read_time=None): - """ - Reads vector data form a vertex. This function reads a value of a specified vertex - from a dataID. - - Parameters - ---------- - mesh_name : str - Name of the mesh to read from. - data_name : str - ID to read from. - vertex_id : int - Index of the vertex. - relative_read_time : double - Point in time where data is read relative to the beginning of the current time step - - Returns - ------- - value : numpy.ndarray - Contains the read data. - - Notes - ----- - Previous calls: - count of available elements at value matches the configured dimension - initialize() has been called - - Examples - -------- - Read vector data for 2D problem: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> value = interface.read_vector_data(mesh_name, data_name, vertex_id) - >>> value.shape - (1, 2) - - Read vector data for 3D problem: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> value = interface.read_vector_data(mesh_name, data_name, vertex_id) - >>> value.shape - (1, 3) - """ - dimensions = self.get_dimensions() - cdef np.ndarray[double, ndim=1] _value = np.empty(dimensions, dtype=np.double) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - if relative_read_time is None: - self.thisptr.readVectorData ( mesh_name_py_bytes, data_name_py_bytes, vertex_id, _value.data) - else: - self.thisptr.readVectorData ( mesh_name_py_bytes, data_name_py_bytes, vertex_id, relative_read_time, _value.data) - - return _value - - def read_block_scalar_data (self, mesh_name, data_name, vertex_ids, relative_read_time=None): - """ - Reads scalar data as a block. This function reads values of specified vertices from a dataID. - Values are provided as a block of continuous memory. - - Parameters - ---------- - mesh_name : str - Name of the mesh to read from. - data_name : str - ID to read from. - vertex_ids : array_like - Indices of the vertices. - relative_read_time : double - Point in time where data is read relative to the beginning of the current time step - - Returns - ------- - values : numpy.ndarray - Contains the read data. - - Notes - ----- - Previous calls: - count of available elements at values matches the given size - count of available elements at vertex_ids matches the given size - initialize() has been called + >>> (5, 2) - Examples - -------- - Read block scalar data for 2D and 3D problems with 5 vertices: + Read vector data for a 3D system with 5 vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" >>> vertex_ids = [1, 2, 3, 4, 5] - >>> values = interface.read_block_scalar_data(mesh_name, data_name, vertex_ids) - >>> values.size - >>> 5 - + >>> values = read_data(mesh_name, data_name, vertex_ids) + >>> values.shape + >>> (5, 3) """ - check_array_like(vertex_ids, "vertex_ids", "read_block_scalar_data") + check_array_like(vertex_ids, "vertex_ids", "read_data") - cdef np.ndarray[int, ndim=1] _vertex_ids = np.ascontiguousarray(vertex_ids, dtype=np.int32) - size = _vertex_ids.size - cdef np.ndarray[double, ndim=1] _values = np.empty(size, dtype=np.double) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - if relative_read_time is None: - self.thisptr.readBlockScalarData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, _values.data) + if len(vertex_ids) == 0: + size = 0 + dimensions = self.get_data_dimensions(mesh_name, data_name) + elif self.get_data_dimensions(mesh_name, data_name) == 1: + size = len(vertex_ids) + dimensions = 1 else: - self.thisptr.readBlockScalarData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, relative_read_time, _values.data) - - return _values - - def read_scalar_data (self, mesh_name, data_name, vertex_id, relative_read_time=None): - """ - Reads scalar data of a vertex. This function needs a value of a specified vertex from a dataID. - - Parameters - ---------- - mesh_name : str - Name of the mesh to read to. - data_name : str - ID to read from. - vertex_id : int - Index of the vertex. - relative_read_time : double - Point in time where data is read relative to the beginning of the current time step - - Returns - ------- - value : double - Contains the read value + size = len(vertex_ids) + dimensions = self.get_data_dimensions(mesh_name, data_name) - Notes - ----- - Previous calls: - initialize() has been called. + cdef vector[int] cpp_ids = vertex_ids + cdef vector[double] cpp_values = [-1 for _ in range(size * dimensions)] - Examples - -------- - Read scalar data for 2D and 3D problems: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> value = interface.read_scalar_data(mesh_name, data_name, vertex_id) - """ - cdef double _value + self.thisptr.readData (convert(mesh_name), convert(data_name), cpp_ids, relative_read_time, cpp_values) - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() + cdef np.ndarray[double, ndim=1] np_values = np.array(cpp_values, dtype=np.double) - if relative_read_time is None: - self.thisptr.readScalarData ( mesh_name_py_bytes, data_name_py_bytes, vertex_id, _value) + if len(vertex_ids) == 0: + return np_values.reshape((size)) + elif self.get_data_dimensions(mesh_name, data_name) == 1: + return np_values.reshape((size)) else: - self.thisptr.readScalarData ( mesh_name_py_bytes, data_name_py_bytes, vertex_id, relative_read_time, _value) + return np_values.reshape((size, dimensions)) - return _value - def write_block_vector_gradient_data (self, mesh_name, data_name, vertex_ids, gradientValues): + def write_gradient_data (self, mesh_name, data_name, vertex_ids, gradients): """ - Writes vector gradient data given as block. This function writes gradient values of specified vertices to a dataID. + Writes 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 of vertices and D = number of gradient components. @@ -1112,7 +914,7 @@ cdef class Interface: Data name to write to. vertex_ids : array_like Indices of the vertices. - gradientValues : array_like + gradients : array_like Gradient values differentiated in the spacial direction (dx, dy) for 2D space, (dx, dy, dz) for 3D space Notes @@ -1125,219 +927,40 @@ cdef class Interface: Examples -------- - Write block gradient vector data for a 2D problem with 2 vertices: + Write gradient vector data for a 2D problem with 2 vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" >>> 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(mesh_name, data_name, vertex_ids, gradientValues) + >>> gradients = np.array([[v1x_dx, v1y_dx, v1x_dy, v1y_dy], [v2x_dx, v2y_dx, v2x_dy, v2y_dy]]) + >>> participant.write_gradient_data(mesh_name, data_name, vertex_ids, gradients) - Write block vector data for a 3D (D=3) problem with 2 (N=2) vertices: + Write vector data for a 3D problem with 2 vertices: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" >>> 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(mesh_name, data_name, vertex_ids, gradientValues) + >>> gradients = 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]]) + >>> participant.write_gradient_data(mesh_name, data_name, vertex_ids, gradients) """ - check_array_like(vertex_ids, "vertex_ids", "write_block_vector_gradient_data") - check_array_like(gradientValues, "gradientValues", "write_block_vector_gradient_data") + check_array_like(vertex_ids, "vertex_ids", "write_gradient_data") + check_array_like(gradients, "gradients", "write_gradient_data") - if not isinstance(gradientValues, np.ndarray): - gradientValues = np.asarray(gradientValues) + if not isinstance(gradients, np.ndarray): + gradients = np.asarray(gradients) - 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: + if len(gradients) > 0: + size, dimensions = gradients.shape + assert dimensions == self.get_mesh_dimensions(mesh_name) * self.get_data_dimensions(mesh_name, data_name), "Dimensions of vector data in write_gradient_data does not match with dimensions in problem definition. Provided dimensions: {}, expected dimensions: {}".format(dimensions, self.get_mesh_dimensions(mesh_name) * self.get_data_dimensions (mesh_name, data_name)) + if len(gradients) == 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) + cdef vector[int] cpp_vertex_ids = vertex_ids + cdef vector[double] cpp_gradients = gradients.flatten() - 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) + assert cpp_gradients.size() == size * self.get_mesh_dimensions(mesh_name) * self.get_data_dimensions (mesh_name, data_name), "Dimension of gradient data provided in write_gradient_data does not match problem definition. Check length of input data provided. Provided size: {}, expected size: {}".format(cpp_gradients.size(), size * self.get_mesh_dimensions(mesh_name) * self.get_data_dimensions (mesh_name, data_name)) + assert cpp_vertex_ids.size() == size, "Vertex IDs are of incorrect length in write_gradient_data. Check length of vertex ids input. Provided size: {}, expected size: {}".format(cpp_vertex_ids.size(), size) - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() + self.thisptr.writeGradientData (convert(mesh_name), convert(data_name), cpp_vertex_ids, cpp_gradients) - self.thisptr.writeBlockVectorGradientData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, _gradientValues.data) - - def write_scalar_gradient_data (self, mesh_name, data_name, 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 - ---------- - mesh_name : str - Name of the mesh to write to. - data_name : str - 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: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> gradientValue = [v5_dx, v5_dy] - >>> interface.write_scalar_gradient_data(mesh_name, data_name, 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()) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - self.thisptr.writeScalarGradientData( mesh_name_py_bytes, data_name_py_bytes, vertex_id, _gradientValues.data) - - def write_vector_gradient_data (self, mesh_name, data_name, 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 - ---------- - mesh_name : str - Name of the mesh to write to. - data_name : str - 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: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_id = 5 - >>> gradientValue = [v5x_dx, v5y_dx, v5x_dy,v5y_dy] - >>> interface.write_vector_gradient_data(mesh_name, data_name, 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()) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - self.thisptr.writeVectorGradientData( mesh_name_py_bytes, data_name_py_bytes, vertex_id, _gradientValues.data) - - def write_block_scalar_gradient_data (self, mesh_name, data_name, 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 - ---------- - mesh_name : str - Name of the mesh to write to. - data_name : str - Data name 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: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> vertex_ids = [1, 2] - >>> gradientValues = np.array([[v1_dx, v1_dy], [v2_dx, v2_dy]]) - >>> interface.write_block_scalar_gradient_data(mesh_name, data_name, vertex_ids, gradientValues) - - Write block scalar data for a 3D (D=3) problem with 2 (N=2) vertices: - >>> mesh_name = "MeshOne" - >>> data_name = "DataOne" - >>> 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(mesh_name, data_name, 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) - - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - - self.thisptr.writeBlockScalarGradientData ( mesh_name_py_bytes, data_name_py_bytes, size, _vertex_ids.data, _gradientValues.data) def requires_gradient_data_for(self, mesh_name, data_name): """ @@ -1360,12 +983,11 @@ cdef class Interface: Check if gradient data is required for a data: >>> mesh_name = "MeshOne" >>> data_name = "DataOne" - >>> interface.is_gradient_data_required(mesh_name, data_name) + >>> participant.is_gradient_data_required(mesh_name, data_name) """ - cdef bytes mesh_name_py_bytes = mesh_name.encode() - cdef bytes data_name_py_bytes = data_name.encode() - return self.thisptr.requiresGradientDataFor( mesh_name_py_bytes, data_name_py_bytes) + return self.thisptr.requiresGradientDataFor(convert(mesh_name), convert(data_name)) + def set_mesh_access_region (self, mesh_name, bounding_box): """ @@ -1419,13 +1041,12 @@ cdef class Interface: assert len(bounding_box) > 0, "Bounding box cannot be empty." - assert len(bounding_box) == (self.get_dimensions() * 2), "Dimensions of bounding box in set_mesh_access_region does not match with dimensions in problem definition." + assert len(bounding_box) == (self.get_mesh_dimensions(mesh_name) * 2), "Dimensions of bounding box in set_mesh_access_region does not match with dimensions in problem definition." - cdef np.ndarray[double, ndim=1] _bounding_box = np.ascontiguousarray(bounding_box, dtype=np.double) + cdef vector[double] cpp_bounding_box = list(bounding_box) - cdef bytes mesh_name_py_bytes = mesh_name.encode() + self.thisptr.setMeshAccessRegion(convert(mesh_name), cpp_bounding_box) - self.thisptr.setMeshAccessRegion( mesh_name_py_bytes, _bounding_box.data) def get_mesh_vertices_and_ids (self, mesh_name): """ @@ -1447,15 +1068,17 @@ cdef class Interface: warnings.warn("The function get_mesh_vertices_and_ids is still experimental.") size = self.get_mesh_vertex_size(mesh_name) - cdef np.ndarray[int, ndim=1] _ids = np.empty(size, dtype=np.int32) - dimensions = self.get_dimensions() - cdef np.ndarray[double, ndim=1] _coordinates = np.empty(size*dimensions, dtype=np.double) + dimensions = self.get_mesh_dimensions(mesh_name) + + cdef vector[int] cpp_ids = [-1 for _ in range(size)] + cdef vector[double] cpp_coordinates = [-1 for _ in range(size * dimensions)] - cdef bytes mesh_name_py_bytes = mesh_name.encode() + self.thisptr.getMeshVerticesAndIDs(convert(mesh_name), cpp_ids, cpp_coordinates) - self.thisptr.getMeshVerticesAndIDs( mesh_name_py_bytes, size, _ids.data, _coordinates.data) + cdef np.ndarray[int, ndim=1] np_ids = np.array(cpp_ids, dtype=np.int32) + cdef np.ndarray[double, ndim=1] np_coordinates = np.array(cpp_coordinates, dtype=np.double) - return _ids, _coordinates.reshape((size, dimensions)) + return np_ids, np_coordinates.reshape((size, dimensions)) def get_version_information (): """ @@ -1463,4 +1086,4 @@ def get_version_information (): ------- Current preCICE version information """ - return SolverInterface.getVersionInformation() + return CppParticipant.getVersionInformation() diff --git a/examples/solverdummy/solverdummy.py b/examples/solverdummy/solverdummy.py index 3af107e9..c2ac95b2 100644 --- a/examples/solverdummy/solverdummy.py +++ b/examples/solverdummy/solverdummy.py @@ -34,42 +34,46 @@ solver_process_index = 0 solver_process_size = 1 -interface = precice.Interface(participant_name, configuration_file_name, - solver_process_index, solver_process_size) +participant = precice.Participant(participant_name, configuration_file_name, + solver_process_index, solver_process_size) -assert (interface.requires_mesh_connectivity_for(mesh_name) is False) +assert (participant.requires_mesh_connectivity_for(mesh_name) is False) -dimensions = interface.get_dimensions() - -vertices = np.zeros((num_vertices, dimensions)) -read_data = np.zeros((num_vertices, dimensions)) -write_data = np.zeros((num_vertices, dimensions)) +vertices = np.zeros((num_vertices, participant.get_mesh_dimensions(mesh_name))) +read_data = np.zeros((num_vertices, participant.get_data_dimensions(mesh_name, read_data_name))) +write_data = np.zeros((num_vertices, participant.get_data_dimensions(mesh_name, write_data_name))) for x in range(num_vertices): - for y in range(0, dimensions): + for y in range(participant.get_mesh_dimensions(mesh_name)): vertices[x, y] = x + + for y in range(participant.get_data_dimensions(mesh_name, read_data_name)): read_data[x, y] = x + + for y in range(participant.get_data_dimensions(mesh_name, write_data_name)): write_data[x, y] = x -vertex_ids = interface.set_mesh_vertices(mesh_name, vertices) +vertex_ids = participant.set_mesh_vertices(mesh_name, vertices) -dt = interface.initialize() +participant.initialize() -while interface.is_coupling_ongoing(): - if interface.requires_writing_checkpoint(): +while participant.is_coupling_ongoing(): + if participant.requires_writing_checkpoint(): print("DUMMY: Writing iteration checkpoint") - read_data = interface.read_block_vector_data(mesh_name, read_data_name, vertex_ids) + dt = participant.get_max_time_step_size() + read_data = participant.read_data(mesh_name, read_data_name, vertex_ids, dt) write_data = read_data + 1 - interface.write_block_vector_data(mesh_name, write_data_name, vertex_ids, write_data) + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) print("DUMMY: Advancing in time") - dt = interface.advance(dt) + dt = participant.get_max_time_step_size() + participant.advance(dt) - if interface.requires_reading_checkpoint(): + if participant.requires_reading_checkpoint(): print("DUMMY: Reading iteration checkpoint") -interface.finalize() +participant.finalize() print("DUMMY: Closing python solver dummy...") diff --git a/precice/__init__.py b/precice/__init__.py index 45f24cb2..0022eb2f 100644 --- a/precice/__init__.py +++ b/precice/__init__.py @@ -2,14 +2,7 @@ __version__ = "unknown" import warnings -from cyprecice import Interface, get_version_information - - -def SolverInterface(*args): - """ - This is just a dummy function to avoid wrong usage of the interface. Please use precice.Interface, if you want to establish a connection to preCICE. See https://github.com/precice/python-bindings/issues/92 for more information. - """ - warnings.warn("please use precice.Interface to create the interface to C++ preCICE. Note that this function (precice.SolverInterface) does not do anything but throwing this warning. See https://github.com/precice/python-bindings/issues/92 for more information.") +from cyprecice import Participant, get_version_information __version__ = get_versions()['version'] diff --git a/setup.py b/setup.py index 165469d0..dd16072a 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ def get_extensions(is_test): link_args += pkgconfig.libs('libprecice').split() if is_test: bindings_sources.append(os.path.join(PYTHON_BINDINGS_PATH, "test", - "SolverInterface.cpp")) + "Participant.cpp")) return [ Extension( diff --git a/test/Participant.cpp b/test/Participant.cpp new file mode 100644 index 00000000..ea9b35dc --- /dev/null +++ b/test/Participant.cpp @@ -0,0 +1,338 @@ +#include "precice/Participant.hpp" +#include "precice/Tooling.hpp" +#include +#include +#include +#include + +std::string fake_version; +std::vector fake_read_write_buffer; +int fake_mesh_dimensions; +int fake_scalar_data_dimensions; +int fake_vector_data_dimensions; +std::vector fake_ids; +int n_fake_vertices; +std::string fake_mesh_name; +std::string fake_scalar_data_name; +std::string fake_vector_data_name; +int fake_data_id; +std::vector fake_bounding_box; +std::vector fake_coordinates; + +namespace precice { + +namespace impl{ +class ParticipantImpl{}; +} + +Participant:: Participant +( + precice::string_view participantName, + precice::string_view configurationFileName, + int solverProcessIndex, + int solverProcessSize ) +{ + fake_version = "dummy"; + fake_read_write_buffer = std::vector(); + fake_mesh_dimensions = 3; + fake_scalar_data_dimensions = 1; + fake_vector_data_dimensions = 3; + fake_data_id = 15; + fake_mesh_name = "FakeMesh"; + fake_scalar_data_name = "FakeScalarData"; + fake_vector_data_name = "FakeVectorData"; + n_fake_vertices = 3; + fake_ids.resize(n_fake_vertices); + std::iota(fake_ids.begin(), fake_ids.end(), 0); + fake_bounding_box.resize(fake_mesh_dimensions*2); + std::iota(fake_bounding_box.begin(), fake_bounding_box.end(), 0); + fake_coordinates.resize(n_fake_vertices*fake_mesh_dimensions); + std::iota(fake_coordinates.begin(), fake_coordinates.end(), 0); +} + +Participant::Participant( + precice::string_view participantName, + precice::string_view configurationFileName, + int solverProcessIndex, + int solverProcessSize, + void * communicator) +{ + fake_version = "dummy"; + fake_read_write_buffer = std::vector(); + fake_mesh_dimensions = 3; + fake_scalar_data_dimensions = 1; + fake_vector_data_dimensions = 3; + fake_data_id = 15; + fake_mesh_name = "FakeMesh"; + fake_scalar_data_name = "FakeScalarData"; + fake_vector_data_name = "FakeVectorData"; + n_fake_vertices = 3; + fake_ids.resize(n_fake_vertices); + std::iota(fake_ids.begin(), fake_ids.end(), 0); + fake_bounding_box.resize(fake_mesh_dimensions*2); + std::iota(fake_bounding_box.begin(), fake_bounding_box.end(), 0); +} + +Participant::~Participant() = default; + +void Participant:: initialize() +{ +} + +void Participant:: advance +( + double computedTimestepLength) +{ +} + +void Participant:: finalize() +{} + +int Participant:: getMeshDimensions +( + precice::string_view meshName) const +{ + return fake_mesh_dimensions; +} + +int Participant:: getDataDimensions +( + precice::string_view meshName, + precice::string_view dataName) const +{ + if (dataName.data() == fake_scalar_data_name) { + return fake_scalar_data_dimensions; + } else if (dataName.data() == fake_vector_data_name) { + return fake_vector_data_dimensions; + } else { + return -1; + } +} + +bool Participant:: isCouplingOngoing() const +{ + return 0; +} + +bool Participant:: isTimeWindowComplete() const +{ + return 0; +} + +double Participant:: getMaxTimeStepSize() const +{ + return -1.0; +} + +bool Participant:: requiresInitialData() +{ + return 0; +} + +bool Participant:: requiresReadingCheckpoint() +{ + return 0; +} + +bool Participant:: requiresWritingCheckpoint() +{ + return 0; +} + +bool Participant:: hasMesh +( + precice::string_view meshName ) const +{ + return 0; +} + +bool Participant:: requiresMeshConnectivityFor +( + precice::string_view meshName) const +{ + return 0; +} + +bool Participant:: requiresGradientDataFor +( + precice::string_view meshName, + precice::string_view dataName) const +{ + return 0; +} + +bool Participant:: hasData +( + precice::string_view meshName, + precice::string_view dataName) const +{ + return 0; +} + +int Participant:: setMeshVertex +( + precice::string_view meshName, + precice::span position ) +{ + return 0; +} + +int Participant:: getMeshVertexSize +( + precice::string_view meshName) const +{ + return n_fake_vertices; +} + +void Participant:: setMeshVertices +( + precice::string_view meshName, + precice::span positions, + precice::span ids) +{ + if(ids.size() > 0) { + assert (ids.size() == fake_ids.size()); + std::copy(fake_ids.begin(), fake_ids.end(), ids.data()); + } +} + +void Participant:: setMeshEdge +( + precice::string_view meshName, + int firstVertexID, + int secondVertexID) +{} + +void Participant::setMeshEdges( + precice::string_view meshName, + precice::span vertices) +{} + +void Participant:: setMeshTriangle +( + precice::string_view meshName, + int firstVertexID, + int secondVertexID, + int thirdVertexID ) +{} + +void Participant:: setMeshTriangles +( + precice::string_view meshName, + precice::span vertices ) +{} + +void Participant:: setMeshQuad +( + precice::string_view meshName, + int firstVertexID, + int secondVertexID, + int thirdVertexID, + int fourthVertexID ) +{} + +void Participant:: setMeshQuads +( + precice::string_view meshName, + precice::span vertices) +{} + +void Participant::setMeshTetrahedron +( + precice::string_view meshName, + int firstVertexID, + int secondVertexID, + int thirdVertexID, + int fourthVertexID) +{} + +void Participant::setMeshTetrahedra +( + precice::string_view meshName, + precice::span vertices) +{} + +void Participant:: writeData +( + precice::string_view meshName, + precice::string_view dataName, + precice::span vertices, + precice::span values) +{ + fake_read_write_buffer.clear(); + + for(const double value: values) { + fake_read_write_buffer.push_back(value); + } +} + +void Participant:: readData +( + precice::string_view meshName, + precice::string_view dataName, + precice::span vertices, + double relativeReadTime, + precice::span values) const +{ + if (dataName.data() == fake_scalar_data_name) { + for(const int id: vertices) { + values[id] = fake_read_write_buffer[id]; + } + } else if (dataName.data() == fake_vector_data_name) { + for(const int id: vertices) { + for(int d = 0; d < fake_vector_data_dimensions; d++) { + const int linearized_id = fake_vector_data_dimensions * id + d; + values[linearized_id] = fake_read_write_buffer[linearized_id]; + } + } + } +} + +void Participant:: setMeshAccessRegion +( + precice::string_view meshName, + precice::span boundingBox ) const +{ + assert(meshName == fake_mesh_name); + + for(std::size_t i = 0; i < fake_bounding_box.size(); i++){ + assert(boundingBox[i] == fake_bounding_box[i]); + } +} + +void Participant:: getMeshVerticesAndIDs +( + precice::string_view meshName, + precice::span valueIndices, + precice::span coordinates ) const +{ + assert(meshName == fake_mesh_name); + assert(valueIndices.size() == fake_ids.size()); + assert(coordinates.size() == fake_coordinates.size()); + + for(std::size_t i = 0; i < fake_ids.size(); i++){ + valueIndices[i] = fake_ids[i]; + } + for(std::size_t i = 0; i < fake_coordinates.size(); i++){ + coordinates[i] = fake_coordinates[i]; + } +} + +void Participant::writeGradientData( + precice::string_view meshName, + precice::string_view dataName, + precice::span vertices, + precice::span gradients) +{ + fake_read_write_buffer.clear(); + for (const double gradient: gradients) { + fake_read_write_buffer.push_back(gradient); + } +} + +std::string getVersionInformation() +{ + return fake_version; +} + +} // namespace precice \ No newline at end of file diff --git a/test/SolverInterface.cpp b/test/SolverInterface.cpp deleted file mode 100644 index 270eaf29..00000000 --- a/test/SolverInterface.cpp +++ /dev/null @@ -1,465 +0,0 @@ -#include "precice/SolverInterface.hpp" -#include "precice/Tooling.hpp" -#include -#include -#include -#include -#include - -std::string fake_version; -std::vector fake_read_write_buffer; -int fake_dimensions; -std::vector fake_ids; -int n_fake_vertices; -std::string fake_mesh_name; -std::string fake_data_name; -int fake_data_id; -std::vector fake_bounding_box; -std::vector fake_coordinates; - -namespace precice { - -namespace impl{ -class SolverInterfaceImpl{}; -} - -SolverInterface:: SolverInterface -( - std::string_view participantName, - std::string_view configurationFileName, - int solverProcessIndex, - int solverProcessSize ) -{ - fake_version = "dummy"; - fake_read_write_buffer = std::vector(); - fake_dimensions = 3; - fake_data_id = 15; - fake_mesh_name = "FakeMesh"; - fake_data_name = "FakeData"; - n_fake_vertices = 3; - fake_ids.resize(n_fake_vertices); - std::iota(fake_ids.begin(), fake_ids.end(), 0); - fake_bounding_box.resize(fake_dimensions*2); - std::iota(fake_bounding_box.begin(), fake_bounding_box.end(), 0); - fake_coordinates.resize(n_fake_vertices*fake_dimensions); - std::iota(fake_coordinates.begin(), fake_coordinates.end(), 0); -} - -SolverInterface::SolverInterface( - std::string_view participantName, - std::string_view configurationFileName, - int solverProcessIndex, - int solverProcessSize, - void * communicator) -{ - fake_version = "dummy"; - fake_read_write_buffer = std::vector(); - fake_dimensions = 3; - fake_data_id = 15; - fake_mesh_name = "FakeMesh"; - fake_data_name = "FakeData"; - n_fake_vertices = 3; - fake_ids.resize(n_fake_vertices); - std::iota(fake_ids.begin(), fake_ids.end(), 0); - fake_bounding_box.resize(fake_dimensions*2); - std::iota(fake_bounding_box.begin(), fake_bounding_box.end(), 0); -} - -SolverInterface::~SolverInterface() = default; - -double SolverInterface:: initialize() -{ - return -1; -} - -double SolverInterface:: advance -( - double computedTimestepLength ) -{ - return -1; -} - -void SolverInterface:: finalize() -{} - -int SolverInterface:: getDimensions() const -{ - return fake_dimensions; -} - -bool SolverInterface:: isCouplingOngoing() const -{ - return 0; -} - -bool SolverInterface:: isTimeWindowComplete() const -{ - return 0; -} - -bool SolverInterface:: requiresInitialData() -{ - return 0; -} - -bool SolverInterface:: requiresReadingCheckpoint() -{ - return 0; -} - -bool SolverInterface:: requiresWritingCheckpoint() -{ - return 0; -} - -bool SolverInterface:: hasMesh -( - std::string_view meshName ) const -{ - return 0; -} - -bool SolverInterface:: requiresMeshConnectivityFor -( - std::string_view meshName) const -{ - return 0; -} - -bool SolverInterface::requiresGradientDataFor -( - std::string_view meshName, - std::string_view dataName) const -{ - return 0; -} - -bool SolverInterface:: hasData -( - std::string_view dataName, - std::string_view meshName) const -{ - return 0; -} - -int SolverInterface:: setMeshVertex -( - std::string_view meshName, - const double* position ) -{ - return 0; -} - -int SolverInterface:: getMeshVertexSize -( - std::string_view meshName) const -{ - return n_fake_vertices; -} - -void SolverInterface:: setMeshVertices -( - std::string_view meshName, - int size, - const double* positions, - int* ids ) -{ - assert (size == fake_ids.size()); - std::copy(fake_ids.begin(), fake_ids.end(), ids); -} - -void SolverInterface:: setMeshEdge -( - std::string_view meshName, - int firstVertexID, - int secondVertexID ) -{} - -void SolverInterface::setMeshEdges( - std::string_view meshName, - int size, - const int * vertices) -{} - -void SolverInterface:: setMeshTriangle -( - std::string_view meshName, - int firstVertexID, - int secondVertexID, - int thirdVertexID ) -{} - -void SolverInterface:: setMeshTriangles -( - std::string_view meshName, - int size, - const int * vertices ) -{} - -void SolverInterface:: setMeshQuad -( - std::string_view meshName, - int firstVertexID, - int secondVertexID, - int thirdVertexID, - int fourthVertexID ) -{} - -void SolverInterface:: setMeshQuads -( - std::string_view meshName, - int size, - const int * vertices) -{} - -void SolverInterface::setMeshTetrahedron( - std::string_view meshName, - int firstVertexID, - int secondVertexID, - int thirdVertexID, - int fourthVertexID) -{} - -void SolverInterface::setMeshTetrahedra( - std::string_view meshName, - int size, - const int * vertices) -{} - -void SolverInterface:: writeBlockVectorData -( - std::string_view meshName, - std::string_view dataName, - int size, - const int* valueIndices, - const double* values ) -{ - fake_read_write_buffer.clear(); - for(int i = 0; i < size * this->getDimensions(); i++){ - fake_read_write_buffer.push_back(values[i]); - } -} - -void SolverInterface:: writeVectorData -( - std::string_view meshName, - std::string_view dataName, - int valueIndex, - const double* value ) -{ - fake_read_write_buffer.clear(); - for(int i = 0; i < this->getDimensions(); i++){ - fake_read_write_buffer.push_back(value[i]); - } -} - -void SolverInterface:: writeBlockScalarData -( - std::string_view meshName, - std::string_view dataName, - int size, - const int* valueIndices, - const double* values ) -{ - fake_read_write_buffer.clear(); - for(int i = 0; i < size; i++){ - fake_read_write_buffer.push_back(values[i]); - } -} - -void SolverInterface:: writeScalarData -( - std::string_view meshName, - std::string_view dataName, - int valueIndex, - double value ) -{ - fake_read_write_buffer.clear(); - fake_read_write_buffer.push_back(value); -} - -void SolverInterface::writeBlockVectorGradientData( - std::string_view meshName, - std::string_view dataName, - 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( - std::string_view meshName, - std::string_view dataName, - 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( - std::string_view meshName, - std::string_view dataName, - 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( - std::string_view meshName, - std::string_view dataName, - 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]); - } -} - -void SolverInterface:: readBlockVectorData -( - std::string_view meshName, - std::string_view dataName, - int size, - const int* valueIndices, - double* values ) const -{ - for(int i = 0; i < size * this->getDimensions(); i++){ - values[i] = fake_read_write_buffer[i]; - } -} - -void SolverInterface:: readBlockVectorData -( - std::string_view meshName, - std::string_view dataName, - int size, - const int* valueIndices, - double relativeReadTime, - double* values ) const -{ - for(int i = 0; i < size * this->getDimensions(); i++){ - values[i] = fake_read_write_buffer[i]; - } -} - -void SolverInterface:: readVectorData -( - std::string_view meshName, - std::string_view dataName, - int valueIndex, - double* value ) const -{ - for(int i = 0; i < this->getDimensions(); i++){ - value[i] = fake_read_write_buffer[i]; - } -} - -void SolverInterface:: readVectorData -( - std::string_view meshName, - std::string_view dataName, - int valueIndex, - double relativeReadTime, - double* value ) const -{ - for(int i = 0; i < this->getDimensions(); i++){ - value[i] = fake_read_write_buffer[i]; - } -} - -void SolverInterface:: readBlockScalarData -( - std::string_view meshName, - std::string_view dataName, - int size, - const int* valueIndices, - double* values ) const -{ - for(int i = 0; i < size; i++){ - values[i] = fake_read_write_buffer[i]; - } -} - -void SolverInterface:: readBlockScalarData -( - std::string_view meshName, - std::string_view dataName, - int size, - const int* valueIndices, - double relativeReadTime, - double* values ) const -{ - for(int i = 0; i < size; i++){ - values[i] = fake_read_write_buffer[i]; - } -} - -void SolverInterface:: readScalarData -( - std::string_view meshName, - std::string_view dataName, - int valueIndex, - double& value ) const -{ - value = fake_read_write_buffer[0]; -} - -void SolverInterface:: readScalarData -( - std::string_view meshName, - std::string_view dataName, - int valueIndex, - double relativeReadTime, - double& value ) const -{ - value = fake_read_write_buffer[0]; -} - -void SolverInterface:: setMeshAccessRegion -( - std::string_view meshName, - const double* boundingBox ) const -{ - assert(meshName == fake_mesh_name); - - for(std::size_t i = 0; i < fake_bounding_box.size(); i++){ - assert(boundingBox[i] == fake_bounding_box[i]); - } -} - -void SolverInterface:: getMeshVerticesAndIDs -( - std::string_view meshName, - const int size, - int* valueIndices, - double* coordinates ) const -{ - assert(meshName == fake_mesh_name); - assert(size == fake_ids.size()); - - for(std::size_t i = 0; i < fake_ids.size(); i++){ - valueIndices[i] = fake_ids[i]; - } - for(std::size_t i = 0; i < fake_coordinates.size(); i++){ - coordinates[i] = fake_coordinates[i]; - } -} - -std::string getVersionInformation() -{ - return fake_version; -} - -} // namespace precice \ No newline at end of file diff --git a/test/test_bindings_module.py b/test/test_bindings_module.py index c1de6cdc..e7c18d5e 100644 --- a/test/test_bindings_module.py +++ b/test/test_bindings_module.py @@ -10,54 +10,61 @@ class TestBindings(TestCase): """ def test_constructor(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) self.assertTrue(True) def test_constructor_custom_mpi_comm(self): - solver_interface = precice.Interface( + participant = precice.Participant( "test", "dummy.xml", 0, 1, MPI.COMM_WORLD) self.assertTrue(True) def test_version(self): precice.__version__ - def test_get_dimensions(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + def test_get_mesh_dimensions(self): + participant = precice.Participant("test", "dummy.xml", 0, 1) # TODO: it would be nice to be able to mock the output of the interface # directly in the test, not in test/SolverInterface.hpp - fake_dimension = 3 # compare to test/SolverInterface.hpp, fake_dimensions + fake_mesh_dimension = 3 # compare to test/SolverInterface.hpp, fake_mesh_dimension # TODO: it would be nice to be able to mock the output of the interface # directly in the test, not in test/SolverInterface.hpp - self.assertEqual(fake_dimension, solver_interface.get_dimensions()) + self.assertEqual(fake_mesh_dimension, participant.get_mesh_dimensions("dummy")) + + def test_get_data_dimensions(self): + participant = precice.Participant("test", "dummy.xml", 0, 1) + fake_scalar_data_dimension = 1 # compare to test/SolverInterface.hpp, fake_scalar_data_dimension + self.assertEqual(fake_scalar_data_dimension, participant.get_data_dimensions("dummy", "FakeScalarData")) + fake_vector_data_dimension = 3 # compare to test/SolverInterface.hpp, fake_vector_data_dimension + self.assertEqual(fake_vector_data_dimension, participant.get_data_dimensions("dummy", "FakeVectorData")) def test_requires_mesh_connectivity_for(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_bool = 0 # compare to output in test/SolverInterface.cpp fake_mesh_name = "FakeMesh" - self.assertEqual(fake_bool, solver_interface.requires_mesh_connectivity_for(fake_mesh_name)) + self.assertEqual(fake_bool, participant.requires_mesh_connectivity_for(fake_mesh_name)) def test_set_mesh_vertices(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions n_fake_vertices = 3 # compare to test/SolverInterface.cpp, n_fake_vertices positions = np.random.rand(n_fake_vertices, fake_dimension) expected_output = np.array(range(n_fake_vertices)) - actual_output = solver_interface.set_mesh_vertices(fake_mesh_name, positions) + actual_output = participant.set_mesh_vertices(fake_mesh_name, positions) self.assertTrue(np.array_equal(expected_output, actual_output)) def test_set_mesh_vertices_empty(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions n_fake_vertices = 0 # compare to test/SolverInterface.cpp, n_fake_vertices - positions = np.random.rand(n_fake_vertices, fake_dimension) + positions = np.zeros((n_fake_vertices, fake_dimension)) expected_output = np.array(range(n_fake_vertices)) - actual_output = solver_interface.set_mesh_vertices(fake_mesh_name, positions) + actual_output = participant.set_mesh_vertices(fake_mesh_name, positions) self.assertTrue(np.array_equal(expected_output, actual_output)) def test_set_mesh_vertices_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions n_fake_vertices = 3 # compare to test/SolverInterface.cpp, n_fake_vertices @@ -65,20 +72,20 @@ def test_set_mesh_vertices_list(self): positions = list(list(positions[i, j] for j in range( positions.shape[1])) for i in range(positions.shape[0])) expected_output = np.array(range(n_fake_vertices)) - actual_output = solver_interface.set_mesh_vertices(fake_mesh_name, positions) + actual_output = participant.set_mesh_vertices(fake_mesh_name, positions) self.assertTrue(np.array_equal(expected_output, actual_output)) def test_set_mesh_vertices_empty_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name positions = [] n_fake_vertices = 0 expected_output = np.array(range(n_fake_vertices)) - actual_output = solver_interface.set_mesh_vertices(fake_mesh_name, positions) + actual_output = participant.set_mesh_vertices(fake_mesh_name, positions) self.assertTrue(np.array_equal(expected_output, actual_output)) def test_set_mesh_vertices_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions n_fake_vertices = 3 # compare to test/SolverInterface.cpp, n_fake_vertices @@ -86,20 +93,20 @@ def test_set_mesh_vertices_tuple(self): positions = tuple(tuple(positions[i, j] for j in range( positions.shape[1])) for i in range(positions.shape[0])) expected_output = np.array(range(n_fake_vertices)) - actual_output = solver_interface.set_mesh_vertices(fake_mesh_name, positions) + actual_output = participant.set_mesh_vertices(fake_mesh_name, positions) self.assertTrue(np.array_equal(expected_output, actual_output)) def test_set_mesh_vertices_empty_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name positions = () n_fake_vertices = 0 expected_output = np.array(range(n_fake_vertices)) - actual_output = solver_interface.set_mesh_vertices(fake_mesh_name, positions) + actual_output = participant.set_mesh_vertices(fake_mesh_name, positions) self.assertTrue(np.array_equal(expected_output, actual_output)) def test_set_mesh_vertices_mixed(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions n_fake_vertices = 3 # compare to test/SolverInterface.cpp, n_fake_vertices @@ -107,82 +114,84 @@ def test_set_mesh_vertices_mixed(self): positions = list(tuple(positions[i, j] for j in range( positions.shape[1])) for i in range(positions.shape[0])) expected_output = np.array(range(n_fake_vertices)) - actual_output = solver_interface.set_mesh_vertices(fake_mesh_name, positions) + actual_output = participant.set_mesh_vertices(fake_mesh_name, positions) self.assertTrue(np.array_equal(expected_output, actual_output)) def test_set_mesh_vertex(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions position = np.random.rand(fake_dimension) - vertex_id = solver_interface.set_mesh_vertex(fake_mesh_name, position) + vertex_id = participant.set_mesh_vertex(fake_mesh_name, position) self.assertTrue(0 == vertex_id) def test_set_mesh_vertex_empty(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 0 # compare to test/SolverInterface.cpp, fake_dimensions position = np.random.rand(fake_dimension) - vertex_id = solver_interface.set_mesh_vertex(fake_mesh_name, position) + vertex_id = participant.set_mesh_vertex(fake_mesh_name, position) self.assertTrue(0 == vertex_id) def test_set_mesh_vertex_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions position = list(np.random.rand(fake_dimension)) - vertex_id = solver_interface.set_mesh_vertex(fake_mesh_name, position) + vertex_id = participant.set_mesh_vertex(fake_mesh_name, position) self.assertTrue(0 == vertex_id) def test_set_mesh_vertex_empty_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name position = [] - vertex_id = solver_interface.set_mesh_vertex(fake_mesh_name, position) + vertex_id = participant.set_mesh_vertex(fake_mesh_name, position) self.assertTrue(0 == vertex_id) def test_set_mesh_vertex_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions position = tuple(np.random.rand(fake_dimension)) - vertex_id = solver_interface.set_mesh_vertex(fake_mesh_name, position) + vertex_id = participant.set_mesh_vertex(fake_mesh_name, position) self.assertTrue(0 == vertex_id) def test_set_mesh_vertex_empty_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name position = () - vertex_id = solver_interface.set_mesh_vertex(fake_mesh_name, position) + vertex_id = participant.set_mesh_vertex(fake_mesh_name, position) self.assertTrue(0 == vertex_id) def test_get_mesh_vertex_size(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name n_fake_vertices = 3 # compare to test/SolverInterface.cpp, n_fake_vertices - n_vertices = solver_interface.get_mesh_vertex_size(fake_mesh_name) + n_vertices = participant.get_mesh_vertex_size(fake_mesh_name) self.assertTrue(n_fake_vertices == n_vertices) def test_read_write_block_scalar_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = np.array([3, 7, 8], dtype=np.double) - solver_interface.write_block_scalar_data("FakeMesh", "FakeData", np.array([1, 2, 3]), write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array([1, 2, 3])) + participant.write_data("FakeMesh", "FakeScalarData", np.array([0, 1, 2]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", np.array([0, 1, 2]), dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_block_scalar_data_single_float(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = 8 with self.assertRaises(TypeError): - solver_interface.write_block_scalar_data("FakeMesh", "FakeData", 1, write_data) + participant.write_data("FakeMesh", "FakeScalarData", 1, write_data) with self.assertRaises(TypeError): - solver_interface.read_block_scalar_data("FakeMesh", "FakeData", 1) + participant.read_data("FakeMesh", "FakeScalarData", 1) def test_read_write_block_scalar_data_empty(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = np.array([]) - solver_interface.write_block_scalar_data("FakeMesh", "FakeData", [], write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", []) + participant.write_data("FakeMesh", "FakeScalarData", [], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", [], dt) self.assertTrue(len(read_data) == 0) def test_read_write_block_scalar_data_non_contiguous(self): @@ -191,55 +200,62 @@ def test_read_write_block_scalar_data_non_contiguous(self): Note: Check whether np.ndarray is contiguous via np.ndarray.flags. """ - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) dummy_array = np.random.rand(3, 3) write_data = dummy_array[:, 1] assert (write_data.flags["C_CONTIGUOUS"] is False) - solver_interface.write_block_scalar_data("FakeMesh", "FakeData", np.array([1, 2, 3]), write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array([1, 2, 3])) + participant.write_data("FakeMesh", "FakeScalarData", np.array([0, 1, 2]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", np.array([0, 1, 2]), dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_scalar_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = 3 - solver_interface.write_scalar_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_scalar_data("FakeMesh", "FakeData", 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = [3] + participant.write_data("FakeMesh", "FakeScalarData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", [0], dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_block_vector_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = np.array([[3, 7, 8], [7, 6, 5]], dtype=np.double) - solver_interface.write_block_vector_data("FakeMesh", "FakeData", np.array([1, 2]), write_data) - read_data = solver_interface.read_block_vector_data("FakeMesh", "FakeData", np.array([1, 2])) + participant.write_data("FakeMesh", "FakeVectorData", np.array([0, 1]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array([0, 1]), dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_block_vector_data_empty(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = np.array([]) - solver_interface.write_block_vector_data("FakeMesh", "FakeData", [], write_data) - read_data = solver_interface.read_block_vector_data("FakeMesh", "FakeData", []) + participant.write_data("FakeMesh", "FakeVectorData", [], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", [], dt) self.assertTrue(len(read_data) == 0) def test_read_write_block_vector_data_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = [[3, 7, 8], [7, 6, 5]] - solver_interface.write_block_vector_data("FakeMesh", "FakeData", np.array([1, 2]), write_data) - read_data = solver_interface.read_block_vector_data("FakeMesh", "FakeData", np.array([1, 2])) + participant.write_data("FakeMesh", "FakeVectorData", np.array([0, 1]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array([0, 1]), dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_block_vector_data_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = ((3, 7, 8), (7, 6, 5)) - solver_interface.write_block_vector_data("FakeMesh", "FakeData", np.array([1, 2]), write_data) - read_data = solver_interface.read_block_vector_data("FakeMesh", "FakeData", np.array([1, 2])) + participant.write_data("FakeMesh", "FakeVectorData", np.array([0, 1]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array([0, 1]), dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_block_vector_data_mixed(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = [(3, 7, 8), (7, 6, 5)] - solver_interface.write_block_vector_data("FakeMesh", "FakeData", np.array([1, 2]), write_data) - read_data = solver_interface.read_block_vector_data("FakeMesh", "FakeData", np.array([1, 2])) + participant.write_data("FakeMesh", "FakeVectorData", np.array([0, 1]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array([0, 1]), dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_block_vector_data_non_contiguous(self): @@ -248,35 +264,39 @@ def test_read_write_block_vector_data_non_contiguous(self): Note: Check whether np.ndarray is contiguous via np.ndarray.flags. """ - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) size = 6 dummy_array = np.random.rand(size, 5) write_data = dummy_array[:, 1:4] assert (write_data.flags["C_CONTIGUOUS"] is False) vertex_ids = np.arange(size) - solver_interface.write_block_vector_data("FakeMesh", "FakeData", vertex_ids, write_data) - read_data = solver_interface.read_block_vector_data("FakeMesh", "FakeData", vertex_ids) + participant.write_data("FakeMesh", "FakeVectorData", vertex_ids, write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", vertex_ids, dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_vector_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = np.array([1, 2, 3], dtype=np.double) - solver_interface.write_vector_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_vector_data("FakeMesh", "FakeData", 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = np.array([[0, 1, 2]], dtype=np.double) + participant.write_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", [0], dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_vector_data_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = [1, 2, 3] - solver_interface.write_vector_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_vector_data("FakeMesh", "FakeData", 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = [[0, 1, 2]] + participant.write_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", [0], dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_vector_data_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = (1, 2, 3) - solver_interface.write_vector_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_vector_data("FakeMesh", "FakeData", 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = [(1, 2, 3)] + participant.write_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", [0], dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_read_write_vector_data_non_contiguous(self): @@ -285,12 +305,14 @@ def test_read_write_vector_data_non_contiguous(self): Note: Check whether np.ndarray is contiguous via np.ndarray.flags. """ - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) dummy_array = np.random.rand(3, 3) write_data = dummy_array[:, 1] assert (write_data.flags["C_CONTIGUOUS"] is False) - solver_interface.write_vector_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_vector_data("FakeMesh", "FakeData", 1) + write_data = [write_data] + participant.write_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", [0], dt) self.assertTrue(np.array_equal(write_data, read_data)) def test_get_version_information(self): @@ -299,14 +321,14 @@ def test_get_version_information(self): self.assertEqual(version_info, fake_version_info) def test_set_mesh_access_region(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions fake_bounding_box = np.arange(fake_dimension * 2) - solver_interface.set_mesh_access_region(fake_mesh_name, fake_bounding_box) + participant.set_mesh_access_region(fake_mesh_name, fake_bounding_box) def test_get_mesh_vertices_and_ids(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_mesh_name = "FakeMesh" # compare to test/SolverInterface.cpp, fake_mesh_name n_fake_vertices = 3 # compare to test/SolverInterface.cpp, n_fake_vertices fake_dimension = 3 # compare to test/SolverInterface.cpp, fake_dimensions @@ -316,148 +338,162 @@ def test_get_mesh_vertices_and_ids(self): coordinates[i, 0] = i * fake_dimension coordinates[i, 1] = i * fake_dimension + 1 coordinates[i, 2] = i * fake_dimension + 2 - fake_ids, fake_coordinates = solver_interface.get_mesh_vertices_and_ids(fake_mesh_name) + fake_ids, fake_coordinates = participant.get_mesh_vertices_and_ids(fake_mesh_name) self.assertTrue(np.array_equal(fake_ids, vertex_ids)) self.assertTrue(np.array_equal(fake_coordinates, coordinates)) def test_requires_gradient_data_for(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_bool = 0 # compare to output in test/SolverInterface.cpp fake_mesh_name = "FakeMesh" fake_data_name = "FakeName" - self.assertEqual(fake_bool, solver_interface.requires_gradient_data_for(fake_mesh_name, fake_data_name)) + self.assertEqual(fake_bool, participant.requires_gradient_data_for(fake_mesh_name, fake_data_name)) def test_write_block_scalar_gradient_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = np.array([[1, 2, 3], [6, 7, 8], [9, 10, 11]], dtype=np.double) - solver_interface.write_block_scalar_gradient_data("FakeMesh", "FakeData", np.array([1, 2, 3]), write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(9))) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = np.array([[0, 1, 2], [6, 7, 8], [9, 10, 11]], dtype=np.double) + participant.write_gradient_data("FakeMesh", "FakeScalarData", np.array([0, 1, 2]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", np.array(range(9)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_block_scalar_gradient_data_single_float(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_dimension = 3 - n_fake_vertices = 4 + n_fake_vertices = 1 vertex_ids = np.arange(n_fake_vertices) write_data = np.random.rand(n_fake_vertices, fake_dimension) - solver_interface.write_block_scalar_gradient_data("FakeMesh", "FakeData", vertex_ids, write_data) - read_data = solver_interface.read_block_vector_data("FakeMesh", "FakeData", vertex_ids) - self.assertTrue(np.array_equal(write_data, read_data)) + participant.write_gradient_data("FakeMesh", "FakeScalarData", vertex_ids, write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", np.arange(n_fake_vertices * fake_dimension), dt) + self.assertTrue(np.array_equal(write_data.flatten(), read_data)) def test_write_block_scalar_gradient_data_empty(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = np.array([]) - solver_interface.write_block_scalar_gradient_data("FakeMesh", "FakeData", [], write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", []) + participant.write_gradient_data("FakeMesh", "FakeScalarData", [], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", [], dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_block_scalar_gradient_data_non_contiguous(self): """ - Tests behaviour of solver interface, if a non contiguous array is passed to the interface. - + Tests behavior of solver interface, if a non contiguous array is passed to the interface. Note: Check whether np.ndarray is contiguous via np.ndarray.flags. """ - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) dummy_array = np.random.rand(3, 9) write_data = dummy_array[:, 3:6] assert write_data.flags["C_CONTIGUOUS"] is False - solver_interface.write_block_scalar_gradient_data("FakeMesh", "FakeData", np.array([1, 2, 3]), write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(9))) + participant.write_gradient_data("FakeMesh", "FakeScalarData", np.array([0, 1, 2]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeScalarData", np.array(range(9)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_scalar_gradient_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_dimension = 3 - write_data = np.random.rand(fake_dimension) - solver_interface.write_scalar_gradient_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_vector_data("FakeMesh", "FakeData", 1) + write_data = [np.random.rand(fake_dimension)] + participant.write_gradient_data("FakeMesh", "FakeScalarData", [0], write_data) + dt = 1 + # Gradient data is essential vector data, hence the appropriate data name is used here + read_data = participant.read_data("FakeMesh", "FakeVectorData", [0], dt) self.assertTrue(np.array_equiv(write_data, read_data)) def test_write_block_vector_gradient_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) fake_dimension = 3 n_fake_vertices = 4 vertex_ids = np.arange(n_fake_vertices) write_data = np.random.rand(n_fake_vertices, fake_dimension * fake_dimension) - solver_interface.write_block_vector_gradient_data("FakeMesh", "FakeData", vertex_ids, write_data) - read_data = solver_interface.read_block_vector_data( - "FakeMesh", "FakeData", np.array(range(n_fake_vertices * fake_dimension))) + participant.write_gradient_data("FakeMesh", "FakeVectorData", vertex_ids, write_data) + dt = 1 + read_data = participant.read_data( + "FakeMesh", "FakeVectorData", np.array(range(n_fake_vertices * fake_dimension)), dt) self.assertTrue(np.array_equiv(write_data.flatten(), read_data.flatten())) def test_write_block_vector_gradient_data_empty(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = np.array([]) - solver_interface.write_block_vector_gradient_data("FakeMesh", "FakeData", [], write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", []) + participant.write_gradient_data("FakeMesh", "FakeVectorData", [], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", [], dt) self.assertTrue(len(read_data) == 0) def test_write_block_vector_gradient_data_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = [[3.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0], [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 6.0, 5.0]] - solver_interface.write_block_vector_gradient_data("FakeMesh", "FakeData", np.array([1, 2]), write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(18))) + participant.write_gradient_data("FakeMesh", "FakeVectorData", np.array([0, 1]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(6)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_block_vector_gradient_data_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = ((1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 3.0, 7.0, 8.0), (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 6.0, 5.0)) - solver_interface.write_block_vector_gradient_data("FakeMesh", "FakeData", np.array([1, 2]), write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(18))) + participant.write_gradient_data("FakeMesh", "FakeVectorData", np.array([0, 1]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(6)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_block_vector_gradient_data_mixed(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) write_data = [(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 3.0, 7.0, 8.0), (4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 7.0, 6.0, 5.0)] - solver_interface.write_block_vector_gradient_data("FakeMesh", "FakeData", np.array([1, 2]), write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(18))) + participant.write_gradient_data("FakeMesh", "FakeVectorData", np.array([0, 1]), write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(6)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_block_vector_gradient_data_non_contiguous(self): """ - Tests behaviour of solver interface, if a non contiguous array is passed to the interface. - + Tests behavior of solver interface, if a non contiguous array is passed to the interface. Note: Check whether np.ndarray is contiguous via np.ndarray.flags. """ - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) dummy_array = np.random.rand(3, 15) write_data = dummy_array[:, 2:11] assert write_data.flags["C_CONTIGUOUS"] is False vertex_ids = np.arange(3) - solver_interface.write_block_vector_gradient_data("FakeMesh", "FakeData", vertex_ids, write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(27))) + participant.write_gradient_data("FakeMesh", "FakeVectorData", vertex_ids, write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(9)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_vector_gradient_data(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = np.arange(0, 9, dtype=np.double) - solver_interface.write_vector_gradient_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(9))) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = [np.arange(0, 9, dtype=np.double)] + participant.write_gradient_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(3)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_vector_gradient_data_list(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] - solver_interface.write_vector_gradient_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(9))) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = [[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]] + participant.write_gradient_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(3)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_vector_gradient_data_tuple(self): - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) - write_data = (1.0, 2.0, 3.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0) - solver_interface.write_vector_gradient_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(9))) + participant = precice.Participant("test", "dummy.xml", 0, 1) + write_data = [(1.0, 2.0, 3.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0)] + participant.write_gradient_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(3)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten())) def test_write_vector_gradient_data_non_contiguous(self): """ - Tests behaviour of solver interface, if a non contiguous array is passed to the interface. - + Tests behavior of solver interface, if a non contiguous array is passed to the interface. Note: Check whether np.ndarray is contiguous via np.ndarray.flags. """ - solver_interface = precice.Interface("test", "dummy.xml", 0, 1) + participant = precice.Participant("test", "dummy.xml", 0, 1) dummy_array = np.random.rand(9, 3) write_data = dummy_array[:, 1] assert write_data.flags["C_CONTIGUOUS"] is False - solver_interface.write_vector_gradient_data("FakeMesh", "FakeData", 1, write_data) - read_data = solver_interface.read_block_scalar_data("FakeMesh", "FakeData", np.array(range(9))) + write_data = [write_data] + participant.write_gradient_data("FakeMesh", "FakeVectorData", [0], write_data) + dt = 1 + read_data = participant.read_data("FakeMesh", "FakeVectorData", np.array(range(3)), dt) self.assertTrue(np.array_equiv(np.array(write_data).flatten(), read_data.flatten()))