2#include <Eigen/src/Core/util/Meta.h>
61#include "precice/impl/versions.hpp"
82 int solverProcessIndex,
83 int solverProcessSize,
85 : _accessorName(participantName),
86 _accessorProcessRank(solverProcessIndex),
87 _accessorCommunicatorSize(solverProcessSize)
91 "Passing \"nullptr\" as \"communicator\" to Participant constructor is not allowed. "
92 "Please use the Participant constructor without the \"communicator\" argument, if you don't want to pass an MPI communicator.");
94 "This participant's name is an empty string. "
95 "When constructing a preCICE interface you need to pass the name of the "
96 "participant as first argument to the constructor.");
98 "The solver process index needs to be a non-negative number, not: {}. "
99 "Please check the value given when constructing a preCICE interface.",
102 "The solver process size needs to be a positive number, not: {}. "
103 "Please check the value given when constructing a preCICE interface.",
106 "The solver process index, currently: {} needs to be smaller than the solver process size, currently: {}. "
107 "Please check the values given when constructing a preCICE interface.",
112#ifndef PRECICE_NO_MPI
133 Event e2(
"startProfilingBackend");
144#ifndef PRECICE_NO_MPI
147 "The solver process index given in the preCICE interface constructor({}) does not match the rank of the passed MPI communicator ({}).",
151 "The solver process size given in the preCICE interface constructor({}) does not match the size of the passed MPI communicator ({}).",
180 PRECICE_INFO(
"This is preCICE version {}", PRECICE_VERSION);
181 PRECICE_INFO(
"Revision info: {}", precice::preciceRevision);
187#ifndef PRECICE_NO_DEBUG_LOG
190 " (without debug log)"
192#ifndef PRECICE_NO_TRACE_LOG
195#ifndef PRECICE_NO_ASSERTIONS
200 PRECICE_INFO(
"Configuring preCICE with configuration \"{}\"", configurationFileName);
214 "A parallel participant needs an intra-participant communication");
216 "You cannot use an intra-participant communication with a serial participant. "
217 "If you do not know exactly what an intra-participant communication is and why you want to use it "
218 "you probably just want to remove the intraComm tag from the preCICE configuration.");
226 "In the preCICE configuration, only one participant is defined. "
227 "One participant makes no coupled simulation. "
228 "Please add at least another one.");
251 "Initial data has to be written to preCICE before calling initialize(). "
252 "After defining your mesh, call requiresInitialData() to check if the participant is required to write initial data using the writeData() function.");
260 if (meshContext->provideMesh) {
261 auto &
mesh = *(meshContext->mesh);
263 meshContext->mesh->preprocess();
269 PRECICE_INFO(
"Setting up primary communication to coupling partner/s");
270 for (
auto &m2nPair :
_m2ns) {
271 auto &bm2n = m2nPair.second;
272 bool requesting = bm2n.isRequesting;
273 if (bm2n.m2n->isConnected()) {
274 PRECICE_DEBUG(
"Primary connection {} {} already connected.", (requesting ?
"from" :
"to"), bm2n.remoteName);
276 PRECICE_DEBUG((requesting ?
"Awaiting primary connection from {}" :
"Establishing primary connection to {}"), bm2n.remoteName);
277 bm2n.prepareEstablishment();
278 bm2n.connectPrimaryRanks();
279 PRECICE_DEBUG(
"Established primary connection {} {}", (requesting ?
"from " :
"to "), bm2n.remoteName);
287 PRECICE_INFO(
"Setting up preliminary secondary communication to coupling partner/s");
288 for (
auto &m2nPair :
_m2ns) {
289 auto &bm2n = m2nPair.second;
290 bm2n.preConnectSecondaryRanks();
295 PRECICE_INFO(
"Setting up secondary communication to coupling partner/s");
296 for (
auto &m2nPair :
_m2ns) {
297 auto &bm2n = m2nPair.second;
298 bm2n.connectSecondaryRanks();
299 PRECICE_DEBUG(
"Established secondary connection {} {}", (bm2n.isRequesting ?
"from " :
"to "), bm2n.remoteName);
303 for (
auto &m2nPair :
_m2ns) {
304 m2nPair.second.cleanupEstablishment();
309 watchPoint->initialize();
312 watchIntegral->initialize();
316 const double time = 0.0;
317 const int timeWindow = 1;
321 for (
auto &context :
_accessor->writeDataContexts()) {
322 context.storeBufferedData(time);
348 double computedTimeStepSize)
366 PRECICE_CHECK(computedTimeStepSize > 0.0,
"advance() cannot be called with a negative time step size {}.", computedTimeStepSize);
377 const bool isAtWindowEnd =
_couplingScheme->addComputedTime(computedTimeStepSize);
387 const bool timeWindowComplete =
_couplingScheme->isTimeWindowComplete();
389 handleDataAfterAdvance(isAtWindowEnd, timeWindowComplete, timeSteppedTo, timeAfterAdvance, dataToReceive);
393 PRECICE_DEBUG(
"Mapped {} samples in write mappings and {} samples in read mappings",
414 if (reachedTimeWindowEnd) {
422 if (!reachedTimeWindowEnd) {
429 PRECICE_ASSERT(
math::greaterEquals(timeAfterAdvance, timeSteppedTo),
"We must have stayed or moved forwards in time (min-time-step-size).", timeAfterAdvance, timeSteppedTo);
440 if (reachedTimeWindowEnd) {
448 for (
auto &context :
_accessor->readDataContexts()) {
449 context.resetInitialGuesses();
451 for (
auto &context :
_accessor->writeDataContexts()) {
452 context.resetInitialGuesses();
462 for (
auto &context :
_accessor->writeDataContexts()) {
463 context.storeBufferedData(time);
469 for (
auto &context :
_accessor->usedMeshContexts()) {
470 for (
const auto &
name : context->mesh->availableData()) {
471 context->mesh->data(
name)->timeStepsStorage().trimBefore(time);
478 for (
auto &context :
_accessor->writeDataContexts()) {
479 context.trimAfter(time);
532 return _accessor->usedMeshContext(meshName).mesh->getDimensions();
540 return _accessor->usedMeshContext(meshName).mesh->data(dataName)->getDimensions();
563 const double nextTimeStepSize =
_couplingScheme->getNextTimeStepMaxSize();
571 "preCICE just returned a maximum time step size of {}. Such a small value can happen if you use many substeps per time window over multiple time windows due to added-up differences of machine precision.",
573 return nextTimeStepSize;
621 if (!
_accessor->isDataWrite(meshName, dataName))
636 " data of the received mesh \"{}\" on participant \"{}\".",
640 return context.
mesh->nVertices();
654 context.
mesh->clear();
666 "Cannot set vertex for mesh \"{}\". Expected {} position components but found {}.", meshName,
mesh.
getDimensions(), position.
size());
671 for (
auto &context :
_accessor->writeDataContexts()) {
673 context.resizeBufferTo(newSize);
691 const auto expectedPositionSize = ids.
size() * meshDims;
693 "Input sizes are inconsistent attempting to set vertices on {}D mesh \"{}\". "
694 "You passed {} vertices indices and {} position components, but we expected {} position components ({} x {}).",
695 meshDims, meshName, ids.
size(), positions.
size(), expectedPositionSize, ids.
size(), meshDims);
697 const Eigen::Map<const Eigen::MatrixXd> posMatrix{
699 for (
unsigned long i = 0; i < ids.
size(); ++i) {
705 for (
auto &context :
_accessor->writeDataContexts()) {
707 context.resizeBufferTo(newSize);
727 mesh->createEdge(v0, v1);
744 "Cannot interpret passed vertex IDs attempting to set edges of mesh \"{}\" . "
745 "You passed {} vertices, but we expected an even number.",
746 meshName, vertices.
size());
748 auto end = vertices.
end();
750 return !mesh->isValidVertexID(vid);
758 for (
unsigned long i = 0; i < vertices.
size() / 2; ++i) {
759 auto aid = vertices[2 * i];
760 auto bid = vertices[2 * i + 1];
761 mesh->createEdge(mesh->vertex(aid), mesh->vertex(bid));
783 "setMeshTriangle() was called with repeated Vertex IDs ({}, {}, {}).",
784 first, second, third);
786 vertices[0] = &mesh->vertex(first);
787 vertices[1] = &mesh->vertex(second);
788 vertices[2] = &mesh->vertex(third);
790 vertices[1]->getCoords(), vertices[2]->getCoords())),
791 "setMeshTriangle() was called with vertices located at identical coordinates (IDs: {}, {}, {}).",
792 first, second, third);
794 edges[0] = &mesh->createEdge(*vertices[0], *vertices[1]);
795 edges[1] = &mesh->createEdge(*vertices[1], *vertices[2]);
796 edges[2] = &mesh->createEdge(*vertices[2], *vertices[0]);
798 mesh->createTriangle(*edges[0], *edges[1], *edges[2]);
815 "Cannot interpret passed vertex IDs attempting to set triangles of mesh \"{}\" . "
816 "You passed {} vertices, which isn't dividable by 3.",
817 meshName, vertices.
size());
819 auto end = vertices.
end();
821 return !mesh->isValidVertexID(vid);
829 for (
unsigned long i = 0; i < vertices.
size() / 3; ++i) {
830 auto aid = vertices[3 * i];
831 auto bid = vertices[3 * i + 1];
832 auto cid = vertices[3 * i + 2];
833 mesh->createTriangle(mesh->vertex(aid),
847 second, third, fourth);
850 PRECICE_CHECK(context.
mesh->getDimensions() == 3,
"setMeshQuad is only possible for 3D meshes."
851 " Please set the mesh dimension to 3 in the preCICE configuration file.");
866 "The four vertices that form the quad are not unique. The resulting shape may be a point, line or triangle."
867 "Please check that the adapter sends the four unique vertices that form the quad, or that the mesh on the interface is composed of quads.");
870 PRECICE_CHECK(convexity.convex,
"The given quad is not convex. "
871 "Please check that the adapter send the four correct vertices or that the interface is composed of quads.");
877 double distance02 = (reordered[0]->getCoords() - reordered[2]->getCoords()).norm();
878 double distance13 = (reordered[1]->getCoords() - reordered[3]->getCoords()).norm();
881 if (distance02 <= distance13) {
904 "Cannot interpret passed vertex IDs attempting to set quads of mesh \"{}\" . "
905 "You passed {} vertices, which isn't dividable by 4.",
906 meshName, vertices.
size());
908 auto end = vertices.
end();
910 return !mesh.isValidVertexID(vid);
918 for (
unsigned long i = 0; i < vertices.
size() / 4; ++i) {
919 auto aid = vertices[4 * i];
920 auto bid = vertices[4 * i + 1];
921 auto cid = vertices[4 * i + 2];
922 auto did = vertices[4 * i + 3];
925 PRECICE_CHECK(
utils::unique_elements(vertexIDs),
"The four vertex ID's of the quad nr {} are not unique. Please check that the vertices that form the quad are correct.", i);
929 "The four vertices that form the quad nr {} are not unique. The resulting shape may be a point, line or triangle."
930 "Please check that the adapter sends the four unique vertices that form the quad, or that the mesh on the interface is composed of quads.",
934 PRECICE_CHECK(convexity.convex,
"The given quad nr {} is not convex. "
935 "Please check that the adapter send the four correct vertices or that the interface is composed of quads.",
941 double distance02 = (reordered[0]->getCoords() - reordered[2]->getCoords()).norm();
942 double distance13 = (reordered[1]->getCoords() - reordered[3]->getCoords()).norm();
944 if (distance02 <= distance13) {
964 PRECICE_CHECK(context.
mesh->getDimensions() == 3,
"setMeshTetrahedron is only possible for 3D meshes."
965 " Please set the mesh dimension to 3 in the preCICE configuration file.");
978 mesh->createTetrahedron(A, B, C, D);
995 "Cannot interpret passed vertex IDs attempting to set quads of mesh \"{}\" . "
996 "You passed {} vertices, which isn't dividable by 4.",
997 meshName, vertices.
size());
999 auto end = vertices.
end();
1001 return !mesh->isValidVertexID(vid);
1009 for (
unsigned long i = 0; i < vertices.
size() / 4; ++i) {
1010 auto aid = vertices[4 * i];
1011 auto bid = vertices[4 * i + 1];
1012 auto cid = vertices[4 * i + 2];
1013 auto did = vertices[4 * i + 3];
1014 mesh->createTetrahedron(mesh->vertex(aid),
1029 PRECICE_CHECK(
_state ==
State::Constructed || (
_state ==
State::Initialized &&
isCouplingOngoing()),
"Calling writeData(...) is forbidden if coupling is not ongoing, because the data you are trying to write will not be used anymore. You can fix this by always calling writeData(...) before the advance(...) call in your simulation loop or by using Participant::isCouplingOngoing() to implement a safeguard.");
1039 const auto expectedDataSize = vertices.
size() * dataDims;
1041 "Input sizes are inconsistent attempting to write {}D data \"{}\" to mesh \"{}\". "
1042 "You passed {} vertices and {} data components, but we expected {} data components ({} x {}).",
1043 dataDims, dataName, meshName,
1044 vertices.
size(), values.
size(), expectedDataSize, dataDims, vertices.
size());
1050 PRECICE_ERROR(
"Cannot write data \"{}\" to mesh \"{}\" due to invalid Vertex ID at vertices[{}]. "
1051 "Please make sure you only use the results from calls to setMeshVertex/Vertices().",
1052 dataName, meshName, *
index);
1061 double relativeReadTime,
1068 PRECICE_CHECK(relativeReadTime >= 0,
"readData(...) cannot sample data before the current time.");
1069 PRECICE_CHECK(
isCouplingOngoing() ||
math::equals(relativeReadTime, 0.0),
"Calling readData(...) with relativeReadTime = {} is forbidden if coupling is not ongoing. If coupling finished, only data for relativeReadTime = 0 is available. Please always use precice.getMaxTimeStepSize() to obtain the maximum allowed relativeReadTime.", relativeReadTime);
1080 const auto expectedDataSize = vertices.
size() * dataDims;
1082 "Input/Output sizes are inconsistent attempting to read {}D data \"{}\" from mesh \"{}\". "
1083 "You passed {} vertices and {} data components, but we expected {} data components ({} x {}).",
1084 dataDims, dataName, meshName,
1085 vertices.
size(), values.
size(), expectedDataSize, dataDims, vertices.
size());
1088 PRECICE_ERROR(
"Cannot read data \"{}\" from mesh \"{}\" due to invalid Vertex ID at vertices[{}]. "
1089 "Please make sure you only use the results from calls to setMeshVertex/Vertices().",
1090 dataName, meshName, *
index);
1094 context.
readValues(vertices, readTime, values);
1119 PRECICE_CHECK(context.
hasGradient(),
"Data \"{}\" has no gradient values available. Please set the gradient flag to true under the data attribute in the configuration file.", dataName);
1122 PRECICE_ERROR(
"Cannot write gradient data \"{}\" to mesh \"{}\" due to invalid Vertex ID at vertices[{}]. "
1123 "Please make sure you only use the results from calls to setMeshVertex/Vertices().",
1124 dataName, meshName, *
index);
1129 const auto gradientComponents = meshDims * dataDims;
1130 const auto expectedComponents = vertices.
size() * gradientComponents;
1132 "Input sizes are inconsistent attempting to write gradient for data \"{}\" to mesh \"{}\". "
1133 "A single gradient/Jacobian for {}D data on a {}D mesh has {} components. "
1134 "You passed {} vertices and {} gradient components, but we expected {} gradient components. ",
1136 dataDims, meshDims, gradientComponents,
1137 vertices.
size(), gradients.
size(), expectedComponents);
1157 int dim = mesh->getDimensions();
1159 "Incorrect amount of bounding box components attempting to set the bounding box of {}D mesh \"{}\" . "
1160 "You passed {} limits, but we expected {} ({}x2).",
1161 dim, meshName, boundingBox.
size(), dim * 2, dim);
1167 for (
int d = 0; d < dim; ++d) {
1169 PRECICE_CHECK(boundingBox[2 * d] <= boundingBox[2 * d + 1],
"Your bounding box is ill defined, i.e. it has a negative volume. The required format is [x_min, x_max...]");
1170 bounds[2 * d] = boundingBox[2 * d];
1171 bounds[2 * d + 1] = boundingBox[2 * d + 1];
1176 mesh->expandBoundingBox(providedBoundingBox);
1192 " data of the received mesh \"{}\" on participant \"{}\".",
1201 const auto meshSize = mesh->nVertices();
1202 const auto meshDims = mesh->getDimensions();
1204 "Output size is incorrect attempting to get vertex ids of {}D mesh \"{}\". "
1205 "You passed {} vertices indices, but we expected {}. "
1206 "Use getMeshVertexSize(\"{}\") to receive the required amount of vertices.",
1207 meshDims, meshName, ids.
size(), meshSize, meshName);
1208 const auto expectedCoordinatesSize =
static_cast<unsigned long>(meshDims * meshSize);
1210 "Output size is incorrect attempting to get vertex coordinates of {}D mesh \"{}\". "
1211 "You passed {} coordinate components, but we expected {} ({}x{}). "
1212 "Use getMeshVertexSize(\"{}\") and getMeshDimensions(\"{}\") to receive the required amount components",
1213 meshDims, meshName, coordinates.
size(), expectedCoordinatesSize, meshSize, meshDims, meshName, meshName);
1215 PRECICE_CHECK(ids.
size() <= meshSize,
"The queried size exceeds the number of available points.");
1217 Eigen::Map<Eigen::MatrixXd> posMatrix{
1218 coordinates.
data(), mesh->getDimensions(),
static_cast<EIGEN_DEFAULT_DENSE_INDEX_TYPE
>(ids.
size())};
1220 for (
unsigned long i = 0; i < ids.
size(); i++) {
1222 ids[i] = mesh->vertex(i).getID();
1223 posMatrix.col(i) = mesh->vertex(i).getCoords();
1231 for (
const auto &m2nConf : config->m2ns()) {
1239 comPartner = m2nConf.connector;
1240 isRequesting =
true;
1242 comPartner = m2nConf.acceptor;
1243 isRequesting =
false;
1248 if (participant->getName() == comPartner) {
1252 _m2ns[comPartner] = [&] {
1254 bound.
m2n = m2nConf.m2n;
1271 if (context->provideMesh) {
1273 "Participant \"{}\" cannot provide and receive mesh {}!",
1279 for (
auto &receiverContext : receiver->usedMeshContexts()) {
1280 if (receiverContext->receiveMeshFrom ==
_accessorName && receiverContext->mesh->getName() == context->mesh->getName()) {
1283 if (receiverContext->meshRequirement > context->meshRequirement) {
1284 context->meshRequirement = receiverContext->meshRequirement;
1288 m2n->createDistributedCommunication(context->mesh);
1289 context->partition->addM2N(m2n);
1302 m2n::PtrM2N m2n = m2nConfig->getM2N(receiver, provider);
1303 m2n->createDistributedCommunication(context->mesh);
1304 context->partition->addM2N(m2n);
1305 for (
const MappingContext &mappingContext : context->fromMappingContexts) {
1306 context->partition->addFromMapping(mappingContext.mapping);
1308 for (
const MappingContext &mappingContext : context->toMappingContexts) {
1309 context->partition->addToMapping(mappingContext.mapping);
1320 return lhs->mesh->getName() < rhs->mesh->getName();
1324 if (meshContext->provideMesh)
1325 meshContext->mesh->computeBoundingBox();
1327 meshContext->clearMappings();
1331 meshContext->partition->compareBoundingBoxes();
1341 auto &contexts =
_accessor->usedMeshContexts();
1343 std::sort(contexts.begin(), contexts.end(),
1345 return lhs->mesh->getName() < rhs->mesh->getName();
1349 meshContext->partition->communicate();
1356 for (
auto &m2nPair :
_m2ns) {
1357 if (m2nPair.second.m2n->usesTwoLevelInitialization()) {
1366 [](
MeshContext const *
const meshContext) ->
bool {
1367 return meshContext->provideMesh;
1372 meshContext->partition->compute();
1373 if (not meshContext->provideMesh) {
1374 meshContext->mesh->computeBoundingBox();
1377 meshContext->mesh->allocateDataValues();
1379 const auto requiredSize = meshContext->mesh->nVertices();
1380 for (
auto &context :
_accessor->writeDataContexts()) {
1381 if (context.getMeshName() == meshContext->mesh->getName()) {
1382 context.resizeBufferTo(requiredSize);
1391 using namespace mapping;
1393 if (not context.mapping->hasComputedMapping()) {
1395 "Automatic RBF mapping alias from mesh \"{}\" to mesh \"{}\" in \"{}\" direction resolves to \"{}\" .",
1396 context.mapping->getInputMesh()->getName(), context.mapping->getOutputMesh()->getName(), mappingType, context.mapping->getName());
1397 PRECICE_INFO(
"Computing \"{}\" mapping from mesh \"{}\" to mesh \"{}\" in \"{}\" direction.",
1398 context.mapping->getName(), context.mapping->getInputMesh()->getName(), context.mapping->getOutputMesh()->getName(), mappingType);
1399 context.mapping->computeMapping();
1408 for (
auto &context :
_accessor->writeDataContexts()) {
1409 if (context.hasMapping()) {
1410 PRECICE_DEBUG(
"Map initial write data \"{}\" from mesh \"{}\"", context.getDataName(), context.getMeshName());
1420 for (
auto &context :
_accessor->writeDataContexts()) {
1421 if (context.hasMapping()) {
1422 PRECICE_DEBUG(
"Map write data \"{}\" from mesh \"{}\"", context.getDataName(), context.getMeshName());
1431 for (
auto &context :
_accessor->readDataContexts()) {
1432 if (context.hasMapping()) {
1437 context.clearToDataFor(fromData);
1439 context.trimToDataAfterFor(fromData, startOfTimeWindow);
1449 for (
auto &context :
_accessor->readDataContexts()) {
1450 if (context.hasMapping()) {
1451 PRECICE_DEBUG(
"Map initial read data \"{}\" to mesh \"{}\"", context.getDataName(), context.getMeshName());
1462 for (
auto &context :
_accessor->readDataContexts()) {
1463 if (context.hasMapping()) {
1464 PRECICE_DEBUG(
"Map read data \"{}\" to mesh \"{}\"", context.getDataName(), context.getMeshName());
1475 if (timings.
find(action->getTiming()) != timings.
end()) {
1476 action->performAction();
1496 for (
auto &context :
_accessor->writeDataContexts()) {
1497 context.resetBuffer();
1505 for (
const PtrParticipant &participant : partConfig->getParticipants()) {
1510 PRECICE_ERROR(
"This participant's name, which was specified in the constructor of the preCICE interface as \"{}\", "
1511 "is not defined in the preCICE configuration. "
1512 "Please double-check the correct spelling.",
1538 "Found ambiguous values for the time step size passed to preCICE in \"advance\". On rank {}, the value is {}, while on rank 0, the value is {}.",
1539 secondaryRank, dt, computedTimeStepSize);
1550 [[maybe_unused]]
auto remoteChanges1 =
_couplingScheme->firstSynchronization(localChanges);
1553 [[maybe_unused]]
auto remoteChanges2 =
_couplingScheme->secondSynchronization();
1566 for (
auto &iter :
_m2ns) {
1567 auto bm2n = iter.second;
1569 PRECICE_DEBUG(
"Synchronizing primary rank with {}", bm2n.remoteName);
1570 if (bm2n.isRequesting) {
1571 bm2n.m2n->getPrimaryRankCommunication()->send(ping, 0);
1573 bm2n.m2n->getPrimaryRankCommunication()->receive(receive, 0);
1577 bm2n.m2n->getPrimaryRankCommunication()->receive(receive, 0);
1579 bm2n.m2n->getPrimaryRankCommunication()->send(pong, 0);
1583 PRECICE_DEBUG(
"Closing distributed communication with {}", bm2n.remoteName);
1584 bm2n.m2n->closeDistributedConnections();
1586 PRECICE_DEBUG(
"Closing communication with {}", bm2n.remoteName);
1587 bm2n.m2n->closeConnection();
1595 return *
_accessor->usedMeshContext(meshName).mesh;
#define PRECICE_ERROR(...)
#define PRECICE_WARN_IF(condition,...)
#define PRECICE_DEBUG(...)
#define PRECICE_TRACE(...)
#define PRECICE_INFO_IF(condition,...)
#define PRECICE_INFO(...)
#define PRECICE_CHECK(check,...)
#define PRECICE_VALIDATE_DATA_NAME(mesh, data)
#define PRECICE_REQUIRE_DATA_WRITE(mesh, data)
#define PRECICE_REQUIRE_MESH_USE(name)
#define PRECICE_REQUIRE_DATA_READ(mesh, data)
#define PRECICE_REQUIRE_MESH_MODIFY(name)
#define PRECICE_VALIDATE_DATA(data, size)
#define PRECICE_EXPERIMENTAL_API()
#define PRECICE_VALIDATE_MESH_NAME(name)
#define PRECICE_ASSERT(...)
Main class for preCICE XML configuration tree.
const PtrParticipantConfiguration & getParticipantConfiguration() const
const mesh::PtrMeshConfiguration getMeshConfiguration() const
const m2n::M2NConfiguration::SharedPointer getM2NConfiguration() const
bool waitInFinalize() const
Returns whether participants wait for each other in finalize.
const cplscheme::PtrCouplingSchemeConfiguration getCouplingSchemeConfiguration() const
bool allowsExperimental() const
Returns whether experimental features are allowed or not.
xml::XMLTag & getXMLTag()
Returns root xml tag to start the automatic configuration process.
@ WriteCheckpoint
Is the participant required to write a checkpoint?
@ ReadCheckpoint
Is the participant required to read a previously written checkpoint?
@ InitializeData
Is the initialization of coupling data required?
bool hasGradient() const
Returns whether _providedData has gradient.
int getDataDimensions() const
Get the dimensions of _providedData.
int getSpatialDimensions() const
Get the spatial dimensions of _providedData.
std::optional< std::size_t > locateInvalidVertexID(const Container &c)
CloseChannels
Which channels to close in closeCommunicationChannels()
void writeGradientData(std::string_view meshName, std::string_view dataName, ::precice::span< const VertexID > vertices, ::precice::span< const double > gradients)
Writes vector gradient data to a mesh.
int getMeshVertexSize(std::string_view meshName) const
Returns the number of vertices of a mesh.
utils::MultiLock< std::string > _meshLock
void setMeshQuad(std::string_view meshName, VertexID first, VertexID second, VertexID third, VertexID fourth)
Sets a planar surface mesh quadrangle from vertex IDs.
bool requiresInitialData()
void setMeshTetrahedra(std::string_view meshName, ::precice::span< const VertexID > vertices)
Sets multiple mesh tetrahedra from vertex IDs.
bool requiresGradientDataFor(std::string_view meshName, std::string_view dataName) const
Checks if the given data set requires gradient data. We check if the data object has been initialized...
int getDataDimensions(std::string_view meshName, std::string_view dataName) const
Returns the spatial dimensionality of the given data on the given mesh.
impl::PtrParticipant determineAccessingParticipant(const config::Configuration &config)
Determines participant accessing this interface from the configuration.
void advanceCouplingScheme()
Advances the coupling schemes.
void computePartitions()
Communicate meshes and create partitions.
void setMeshEdge(std::string_view meshName, VertexID first, VertexID second)
Sets a mesh edge from vertex IDs.
std::vector< impl::PtrParticipant > _participants
Holds information about solvers participating in the coupled simulation.
bool requiresMeshConnectivityFor(std::string_view meshName) const
Checks if the given mesh requires connectivity.
void setMeshTriangles(std::string_view meshName, ::precice::span< const VertexID > vertices)
Sets multiple mesh triangles from vertex IDs.
int _executedReadMappings
Counts the amount of samples mapped in read mappings executed in the latest advance.
void performDataActions(const std::set< action::Action::Timing > &timings)
Performs all data actions with given timing.
void setMeshTriangle(std::string_view meshName, VertexID first, VertexID second, VertexID third)
Sets mesh triangle from vertex IDs.
void configurePartitions(const m2n::M2NConfiguration::SharedPointer &m2nConfig)
Determines participants providing meshes to other participants.
bool requiresWritingCheckpoint()
double getMaxTimeStepSize() const
Get the maximum allowed time step size of the current window.
cplscheme::PtrCouplingScheme _couplingScheme
long int _numberAdvanceCalls
Counts calls to advance for plotting.
bool _allowsExperimental
Are experimental API calls allowed?
void handleDataBeforeAdvance(bool reachedTimeWindowEnd, double timeSteppedTo)
Completes everything data-related between adding time to and advancing the coupling scheme.
void setMeshTetrahedron(std::string_view meshName, VertexID first, VertexID second, VertexID third, VertexID fourth)
Set tetrahedron in 3D mesh from vertex ID.
void handleDataAfterAdvance(bool reachedTimeWindowEnd, bool isTimeWindowComplete, double timeSteppedTo, double timeAfterAdvance, const cplscheme::ImplicitData &receivedData)
Completes everything data-related after advancing the coupling scheme.
void samplizeWriteData(double time)
Creates a Stample at the given time for each write Data and zeros the buffers.
void setMeshQuads(std::string_view meshName, ::precice::span< const VertexID > vertices)
Sets multiple mesh quads from vertex IDs.
void getMeshVertexIDsAndCoordinates(std::string_view meshName, ::precice::span< VertexID > ids, ::precice::span< double > coordinates) const
getMeshVertexIDsAndCoordinates Iterates over the region of interest defined by bounding boxes and rea...
int _accessorCommunicatorSize
void closeCommunicationChannels(CloseChannels cc)
Syncs the primary ranks of all connected participants.
void trimSendDataAfter(double time)
Discards send (currently write) data of a participant after a given time when another iteration is re...
std::unique_ptr< profiling::Event > _solverInitEvent
ParticipantImpl(std::string_view participantName, std::string_view configurationFileName, int solverProcessIndex, int solverProcessSize, std::optional< void * > communicator)
Generic constructor for ParticipantImpl.
void advance(double computedTimeStepSize)
Advances preCICE after the solver has computed one time step.
std::string _accessorName
void setMeshAccessRegion(std::string_view meshName, ::precice::span< const double > boundingBox) const
setMeshAccessRegion Define a region of interest on a received mesh (<receive-mesh ....
void writeData(std::string_view meshName, std::string_view dataName, ::precice::span< const VertexID > vertices, ::precice::span< const double > values)
Writes data to a mesh.
bool _accessRegionDefined
setMeshAccessRegion may only be called once
void mapInitialReadData()
~ParticipantImpl()
Destructor.
bool isCouplingOngoing() const
Checks if the coupled simulation is still ongoing.
State _state
The current State of the Participant.
void mapInitialWrittenData()
Computes, and performs write mappings of the initial data in initialize.
impl::PtrParticipant _accessor
void handleExports()
Exports meshes with data and watch point data.
void setMeshVertices(std::string_view meshName, ::precice::span< const double > positions, ::precice::span< VertexID > ids)
Creates multiple mesh vertices.
void resetMesh(std::string_view meshName)
MappedSamples mappedSamples() const
Returns the amount of mapped read and write samples in the last call to advance.
void finalize()
Finalizes preCICE.
bool requiresReadingCheckpoint()
int _executedWriteMappings
Counts the amount of samples mapped in write mappings executed in the latest advance.
void configureM2Ns(const m2n::M2NConfiguration::SharedPointer &config)
void trimReadMappedData(double timeAfterAdvance, bool isTimeWindowComplete, const cplscheme::ImplicitData &fromData)
Removes samples in mapped to data connected to received data via a mapping.
std::map< std::string, m2n::BoundM2N > _m2ns
bool isTimeWindowComplete() const
Checks if the current coupling window is completed.
void setMeshEdges(std::string_view meshName, ::precice::span< const VertexID > vertices)
Sets multiple mesh edges from vertex IDs.
VertexID setMeshVertex(std::string_view meshName, ::precice::span< const double > position)
Creates a mesh vertex.
void syncTimestep(double computedTimeStepSize)
Syncs the time step size between all ranks (all time steps sizes should be the same!...
void readData(std::string_view meshName, std::string_view dataName, ::precice::span< const VertexID > vertices, double relativeReadTime, ::precice::span< double > values) const
Reads data values from a mesh. Values correspond to a given point in time relative to the beginning o...
const mesh::Mesh & mesh(const std::string &meshName) const
Allows to access a registered mesh.
void compareBoundingBoxes()
Communicate bounding boxes and look for overlaps.
bool _waitInFinalize
Are participants waiting for each other in finalize?
void initializeIntraCommunication()
Initializes intra-participant communication.
void resetWrittenData()
Resets written data.
void trimOldDataBefore(double time)
Discards data before the given time for all meshes and data known by this participant.
std::unique_ptr< profiling::Event > _solverAdvanceEvent
void configure(std::string_view configurationFileName)
Configures the coupling interface from the given xml file.
void mapWrittenData(std::optional< double > after=std::nullopt)
Computes, and performs suitable write mappings either entirely or after given time.
void initialize()
Fully initializes preCICE and coupling data.
void computeMappings(std::vector< MappingContext > &contexts, const std::string &mappingType)
Helper for mapWrittenData and mapReadData.
int getMeshDimensions(std::string_view meshName) const
Returns the spatial dimensionality of the given mesh.
Stores one Data object with related mesh. Context stores data to be read from and potentially provide...
void readValues(::precice::span< const VertexID > vertices, double time, ::precice::span< double > values) const
Samples data at a given point in time within the current time window for given indices.
Stores one Data object with related mesh. Context stores data to be written to and potentially provid...
void writeGradientsIntoDataBuffer(::precice::span< const VertexID > vertices, ::precice::span< const double > gradients)
Store gradients in _writeDataBuffer.
void writeValuesIntoDataBuffer(::precice::span< const VertexID > vertices, ::precice::span< const double > values)
Store values in _writeDataBuffer.
An M2N between participants with a configured direction.
An axis-aligned bounding box around a (partition of a) mesh.
Linear edge of a mesh, defined by two Vertex objects.
Container and creator for meshes.
Triangle & createTriangle(Edge &edgeOne, Edge &edgeTwo, Edge &edgeThree)
Creates and initializes a Triangle object.
int getDimensions() const
const std::string & getName() const
Returns the name of the mesh, as set in the config file.
std::size_t nVertices() const
Returns the number of vertices.
bool isValidVertexID(VertexID vertexID) const
Returns true if the given vertexID is valid.
Vertex & createVertex(const Eigen::VectorXd &coords)
Creates and initializes a Vertex object.
void allocateDataValues()
Allocates memory for the vertex data values and corresponding gradient values.
A partition that is provided by the participant.
A partition that is computed from a mesh received from another participant.
static EventRegistry & instance()
Returns the only instance (singleton) of the EventRegistry class.
void startBackend()
Create the file and starts the filestream if profiling is turned on.
void initialize(std::string_view applicationName, int rank=0, int size=1)
Sets the global start time.
void finalize()
Sets the global end time and flushes buffers.
void stop()
Stops a running event.
Class that changes the prefix in its scope.
A C++ 11 implementation of the non-owning C++20 std::span type.
constexpr pointer data() const noexcept
PRECICE_SPAN_NODISCARD constexpr bool empty() const noexcept
constexpr iterator begin() const noexcept
constexpr iterator end() const noexcept
constexpr size_type size() const noexcept
static void barrier()
Synchronizes all ranks.
static bool isPrimary()
True if this process is running the primary rank.
static auto allSecondaryRanks()
Returns an iterable range over salve ranks [1, _size)
static bool isParallel()
True if this process is running in parallel.
static bool isSecondary()
True if this process is running a secondary rank.
static com::PtrCommunication & getCommunication()
Intra-participant communication.
static void configure(Rank rank, int size)
Configures the intra-participant communication.
void add(Key name, bool state)
Adds a lock with a given state.
void clear() noexcept
Removes all known locks.
void lockAll() noexcept
Locks all known locks.
void unlock(const K &name)
Unlocks a given lock.
static void finalizeOrCleanupMPI()
Finalized a managed MPI environment or cleans up after an non-managed session.
static CommStatePtr current()
Returns an owning pointer to the current CommState.
static void initializeOrDetectMPI(std::optional< Communicator > userProvided=std::nullopt)
static void finalize()
Finalizes Petsc environment.
std::string errorInvalidVertexID(int vid)
static constexpr auto errorInvalidVertexIDRange
void setMPIRank(int const rank)
void setParticipant(std::string const &participant)
ConvexityResult isConvexQuad(std::array< Eigen::VectorXd, 4 > coords)
constexpr bool equals(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares two Eigen::MatrixBase for equality up to tolerance.
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type smallerEquals(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
constexpr double NUMERICAL_ZERO_DIFFERENCE
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type greaterEquals(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type greater(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
std::array< Eigen::VectorXd, n > coordsFor(const Mesh &mesh, const std::array< int, n > &vertexIDs)
Given a mesh and an array of vertexIDS, this function returns an array of coordinates of the vertices...
std::array< Vertex *, n > vertexPtrsFor(Mesh &mesh, const std::array< int, n > &vertexIDs)
Given a mesh and an array of vertexIDS, this function returns an array of pointers to vertices.
std::shared_ptr< Partition > PtrPartition
static constexpr FundamentalTag Fundamental
Convenience instance of the FundamentalTag.
static constexpr SynchronizeTag Synchronize
Convenience instance of the SynchronizeTag.
auto reorder_array(const std::array< Index, n > &order, const std::array< T, n > &elements) -> std::array< T, n >
Reorders an array given an array of unique indices.
bool contained(const ELEMENT_T &element, const std::vector< ELEMENT_T > &vec)
Returns true, if given element is in vector, otherwise false.
auto make_array(Elements &&... elements) -> std::array< typename std::common_type< Elements... >::type, sizeof...(Elements)>
Function that generates an array from given elements.
std::pair< InputIt, InputIt > find_first_range(InputIt first, InputIt last, Predicate p)
Finds the first range in [first, last[ that fulfills a predicate.
bool unique_elements(const Container &c, BinaryPredicate p={})
void configure(XMLTag &tag, const precice::xml::ConfigurationContext &context, std::string_view configurationFilename)
Configures the given configuration from file configurationFilename.
T stable_partition(T... args)
Holds a data mapping and related information.
Stores a mesh and related objects and data.
mesh::PtrMesh mesh
Mesh holding the geometry data structure.
mapping::Mapping::MeshRequirement meshRequirement
Determines which mesh type has to be provided by the accessor.
Tightly coupled to the parameters of Participant()