2#include <Eigen/src/Core/util/Meta.h>
65#include "precice/impl/versions.hpp"
86 int solverProcessIndex,
87 int solverProcessSize,
95 "This participant's name is an empty string. "
96 "When constructing a preCICE interface you need to pass the name of the "
97 "participant as first argument to the constructor.");
101 "Passing \"nullptr\" as \"communicator\" to Participant constructor is not allowed. "
102 "Please use the Participant constructor without the \"communicator\" argument, if you don't want to pass an MPI communicator.");
104 "The solver process index needs to be a non-negative number, not: {}. "
105 "Please check the value given when constructing a preCICE interface.",
108 "The solver process size needs to be a positive number, not: {}. "
109 "Please check the value given when constructing a preCICE interface.",
112 "The solver process index, currently: {} needs to be smaller than the solver process size, currently: {}. "
113 "Please check the values given when constructing a preCICE interface.",
122#ifndef PRECICE_NO_MPI
134 "The solver process index given in the preCICE interface constructor({}) does not match the rank of the passed MPI communicator ({}).",
138 "The solver process size given in the preCICE interface constructor({}) does not match the size of the passed MPI communicator ({}).",
143 PRECICE_WARN_IF(communicator.
has_value(),
"preCICE was configured without MPI but you passed an MPI communicator. preCICE ignores the communicator and continues.");
151 Event e2(
"startProfilingBackend");
184 PRECICE_INFO(
"This is preCICE version {}", PRECICE_VERSION);
185 PRECICE_INFO(
"Revision info: {}", precice::preciceRevision);
191#ifndef PRECICE_NO_DEBUG_LOG
194 " (without debug log)"
196#ifndef PRECICE_NO_TRACE_LOG
199#ifndef PRECICE_NO_ASSERTIONS
210 PRECICE_INFO(
"Configuring preCICE with configuration \"{}\"", configurationFileName);
217 "In the preCICE configuration, only one participant is defined. "
218 "One participant makes no coupled simulation. "
219 "Please add at least another one.");
231 "A parallel participant needs an intra-participant communication");
233 "You cannot use an intra-participant communication with a serial participant. "
234 "If you do not know exactly what an intra-participant communication is and why you want to use it "
235 "you probably just want to remove the intraComm tag from the preCICE configuration.");
243 _meshLock.add(meshContext->mesh->getName(),
false);
256 "Initial data has to be written to preCICE before calling initialize(). "
257 "After defining your mesh, call requiresInitialData() to check if the participant is required to write initial data using the writeData() function.");
260 PRECICE_CHECK(
_userEvents.empty(),
"There are unstopped user defined events. Please stop them using stopLastProfilingSection() before calling initialize().");
265 for (
const auto &context :
_accessor->usedMeshContexts()) {
266 if (context->provideMesh) {
267 e.
addData(
"meshSize" + context->mesh->getName(), context->mesh->nVertices());
276 for (
auto &context :
_accessor->writeDataContexts()) {
277 const double startTime = 0.0;
278 context.storeBufferedData(startTime);
311 for (
const auto &context :
_accessor->usedMeshContexts()) {
312 if (context->provideMesh) {
313 e.
addData(
"meshSize" + context->mesh->getName(), context->mesh->nVertices());
331 if (meshContext->provideMesh) {
332 auto &
mesh = *meshContext->mesh;
340 PRECICE_INFO(
"Setting up primary communication to coupling partner/s");
341 Event e2(
"connectPrimaries");
342 for (
auto &m2nPair :
_m2ns) {
343 auto &bm2n = m2nPair.second;
344 bool requesting = bm2n.isRequesting;
345 if (bm2n.m2n->isConnected()) {
346 PRECICE_DEBUG(
"Primary connection {} {} already connected.", (requesting ?
"from" :
"to"), bm2n.remoteName);
348 PRECICE_DEBUG((requesting ?
"Awaiting primary connection from {}" :
"Establishing primary connection to {}"), bm2n.remoteName);
349 bm2n.prepareEstablishment();
351 PRECICE_DEBUG(
"Established primary connection {} {}", (requesting ?
"from " :
"to "), bm2n.remoteName);
358 Event e3(
"repartitioning");
362 PRECICE_INFO(
"Setting up preliminary secondary communication to coupling partner/s");
363 for (
auto &m2nPair :
_m2ns) {
364 auto &bm2n = m2nPair.second;
365 bm2n.preConnectSecondaryRanks();
371 PRECICE_INFO(
"Setting up secondary communication to coupling partner/s");
372 Event e4(
"connectSecondaries");
373 for (
auto &m2nPair :
_m2ns) {
374 auto &bm2n = m2nPair.second;
375 bm2n.connectSecondaryRanks();
376 PRECICE_DEBUG(
"Established secondary connection {} {}", (bm2n.isRequesting ?
"from " :
"to "), bm2n.remoteName);
380 for (
auto &m2nPair :
_m2ns) {
381 m2nPair.second.cleanupEstablishment();
390 watchPoint->initialize();
393 watchIntegral->initialize();
398 double computedTimeStepSize)
404 PRECICE_CHECK(
_userEvents.empty(),
"There are unstopped user defined events. Please stop them using stopLastProfilingSection() before calling advance().");
421 PRECICE_CHECK(computedTimeStepSize > 0.0,
"advance() cannot be called with a negative time step size {}.", computedTimeStepSize);
433 const bool isAtWindowEnd =
_couplingScheme->addComputedTime(computedTimeStepSize);
440 int sumOfChanges =
std::accumulate(totalMeshChanges.begin(), totalMeshChanges.end(), 0);
458 const bool timeWindowComplete =
_couplingScheme->isTimeWindowComplete();
460 handleDataAfterAdvance(isAtWindowEnd, timeWindowComplete, timeSteppedTo, timeAfterAdvance, dataToReceive);
464 PRECICE_DEBUG(
"Mapped {} samples in write mappings and {} samples in read mappings",
495 if (reachedTimeWindowEnd) {
503 if (!reachedTimeWindowEnd) {
510 PRECICE_ASSERT(
math::greaterEquals(timeAfterAdvance, timeSteppedTo),
"We must have stayed or moved forwards in time (min-time-step-size).", timeAfterAdvance, timeSteppedTo);
521 if (reachedTimeWindowEnd) {
528 for (
auto &context :
_accessor->readDataContexts()) {
529 context.invalidateMappingCache();
533 for (
auto &context :
_accessor->writeDataContexts()) {
534 context.invalidateMappingCache();
539 for (
auto &context :
_accessor->readDataContexts()) {
540 context.resetInitialGuesses();
542 for (
auto &context :
_accessor->writeDataContexts()) {
543 context.resetInitialGuesses();
553 for (
auto &context :
_accessor->writeDataContexts()) {
570 context.completeJustInTimeMapping();
571 context.storeBufferedData(
time);
577 for (
auto &context :
_accessor->usedMeshContexts()) {
578 for (
const auto &name : context->mesh->availableData()) {
579 context->mesh->data(name)->timeStepsStorage().trimBefore(
time);
586 for (
auto &context :
_accessor->writeDataContexts()) {
587 context.trimAfter(
time);
633#ifndef PRECICE_NO_GINKGO
647 return _accessor->usedMeshContext(meshName).mesh->getDimensions();
655 return _accessor->usedMeshContext(meshName).mesh->data(dataName)->getDimensions();
678 const double nextTimeStepSize =
_couplingScheme->getNextTimeStepMaxSize();
686 "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.",
688 return nextTimeStepSize;
736 if (!
_accessor->isDataWrite(meshName, dataName))
751 "initialize() has to be called before accessing data of the received mesh \"{}\" on participant \"{}\".",
760 "but no access region was defined although this is necessary for parallel runs. "
761 "Please define an access region using \"setMeshAccessRegion()\" before calling \"getMeshVertexSize()\".",
766 PRECICE_DEBUG(
"Filtered {} of {} vertices out on mesh {} due to the local access region. Mesh size in the access region: {}", context.
mesh->
nVertices() - result, context.
mesh->
nVertices(), meshName, result);
771 "You are calling \"getMeshVertexSize()\" on a received mesh without api-access enabled (<receive-mesh name=\"{0}\" ... api-access=\"false\"/>). "
772 "Note that enabling api-access is required for this function to work properly with direct mesh access and just-in-time mappings.",
783 PRECICE_CHECK(
_allowsRemeshing,
"Cannot reset meshes. This feature needs to be enabled using <precice-configuration experimental=\"1\" allow-remeshing=\"1\">.");
788 PRECICE_CHECK(
_couplingScheme->isTimeWindowComplete(),
"Cannot remesh while subcycling or iterating. Remeshing is only allowed when the time window is completed.");
805 "Cannot set vertex for mesh \"{}\". Expected {} position components but found {}.", meshName,
mesh.getDimensions(), position.
size());
807 auto index =
mesh.createVertex(Eigen::Map<const Eigen::VectorXd>{position.
data(),
mesh.getDimensions()}).getID();
808 mesh.allocateDataValues();
810 const auto newSize =
mesh.nVertices();
811 for (
auto &context :
_accessor->writeDataContexts()) {
812 if (context.getMeshName() ==
mesh.getName()) {
813 context.resizeBufferTo(newSize);
830 const auto meshDims =
mesh.getDimensions();
831 const auto expectedPositionSize = ids.
size() * meshDims;
833 "Input sizes are inconsistent attempting to set vertices on {}D mesh \"{}\". "
834 "You passed {} vertex indices and {} position components, but we expected {} position components ({} x {}).",
835 meshDims, meshName, ids.
size(), positions.
size(), expectedPositionSize, ids.
size(), meshDims);
838 const Eigen::Map<const Eigen::MatrixXd> posMatrix{
839 positions.
data(),
mesh.getDimensions(),
static_cast<EIGEN_DEFAULT_DENSE_INDEX_TYPE
>(ids.
size())};
840 for (
unsigned long i = 0; i < ids.
size(); ++i) {
841 ids[i] =
mesh.createVertex(posMatrix.col(i)).getID();
843 mesh.allocateDataValues();
845 const auto newSize =
mesh.nVertices();
846 for (
auto &context :
_accessor->writeDataContexts()) {
847 if (context.getMeshName() ==
mesh.getName()) {
848 context.resizeBufferTo(newSize);
872 mesh.createEdge(v0, v1);
888 "Cannot interpret passed vertex IDs attempting to set edges of mesh \"{}\" . "
889 "You passed {} vertex indices, but we expected an even number.",
890 meshName, vertices.
size());
892 auto end = vertices.
end();
894 return !mesh.isValidVertexID(vid);
904 for (
unsigned long i = 0; i < vertices.
size() / 2; ++i) {
905 auto aid = vertices[2 * i];
906 auto bid = vertices[2 * i + 1];
930 "setMeshTriangle() was called with repeated Vertex IDs ({}, {}, {}).",
931 first, second, third);
937 mesh.createTriangle(A, B, C);
953 "Cannot interpret passed vertex IDs attempting to set triangles of mesh \"{}\" . "
954 "You passed {} vertex indices, which isn't dividable by 3.",
955 meshName, vertices.
size());
957 auto end = vertices.
end();
959 return !mesh.isValidVertexID(vid);
969 for (
unsigned long i = 0; i < vertices.
size() / 3; ++i) {
970 auto aid = vertices[3 * i];
971 auto bid = vertices[3 * i + 1];
972 auto cid = vertices[3 * i + 2];
973 mesh.createTriangle(
mesh.vertex(aid),
987 second, third, fourth);
1007 "The four vertices that form the quad are not unique. The resulting shape may be a point, line or triangle. "
1008 "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.");
1011 PRECICE_CHECK(convexity.convex,
"The given quad is not convex. "
1012 "Please check that the adapter send the four correct vertices or that the interface is composed of quads.");
1020 double distance02 = (reordered[0]->getCoords() - reordered[2]->getCoords()).norm();
1021 double distance13 = (reordered[1]->getCoords() - reordered[3]->getCoords()).norm();
1024 if (distance02 <= distance13) {
1025 mesh.createTriangle(*reordered[0], *reordered[2], *reordered[1]);
1026 mesh.createTriangle(*reordered[0], *reordered[2], *reordered[3]);
1028 mesh.createTriangle(*reordered[1], *reordered[3], *reordered[0]);
1029 mesh.createTriangle(*reordered[1], *reordered[3], *reordered[2]);
1046 "Cannot interpret passed vertex IDs attempting to set quads of mesh \"{}\" . "
1047 "You passed {} vertex indices, which isn't dividable by 4.",
1048 meshName, vertices.
size());
1050 auto end = vertices.
end();
1052 return !mesh.isValidVertexID(vid);
1060 for (
unsigned long i = 0; i < vertices.
size() / 4; ++i) {
1061 auto aid = vertices[4 * i];
1062 auto bid = vertices[4 * i + 1];
1063 auto cid = vertices[4 * i + 2];
1064 auto did = vertices[4 * i + 3];
1067 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);
1071 "The four vertices that form the quad nr {} are not unique. The resulting shape may be a point, line or triangle. "
1072 "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.",
1076 PRECICE_CHECK(convexity.convex,
"The given quad nr {} is not convex. "
1077 "Please check that the adapter send the four correct vertices or that the interface is composed of quads.",
1085 double distance02 = (reordered[0]->getCoords() - reordered[2]->getCoords()).norm();
1086 double distance13 = (reordered[1]->getCoords() - reordered[3]->getCoords()).norm();
1088 if (distance02 <= distance13) {
1089 mesh.createTriangle(*reordered[0], *reordered[2], *reordered[1]);
1090 mesh.createTriangle(*reordered[0], *reordered[2], *reordered[3]);
1092 mesh.createTriangle(*reordered[1], *reordered[3], *reordered[0]);
1093 mesh.createTriangle(*reordered[1], *reordered[3], *reordered[2]);
1109 "Please set the mesh dimension to 3 in the preCICE configuration file.");
1127 mesh.createTetrahedron(A, B, C, D);
1138 "Please set the mesh dimension to 3 in the preCICE configuration file.");
1145 "Cannot interpret passed vertex IDs attempting to set quads of mesh \"{}\" . "
1146 "You passed {} vertex indices, which isn't dividable by 4.",
1147 meshName, vertices.
size());
1149 auto end = vertices.
end();
1151 return !mesh.isValidVertexID(vid);
1161 for (
unsigned long i = 0; i < vertices.
size() / 4; ++i) {
1162 auto aid = vertices[4 * i];
1163 auto bid = vertices[4 * i + 1];
1164 auto cid = vertices[4 * i + 2];
1165 auto did = vertices[4 * i + 3];
1166 mesh.createTetrahedron(
mesh.vertex(aid),
1181 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.");
1191 const auto expectedDataSize = vertices.
size() * dataDims;
1193 "Input sizes are inconsistent attempting to write {}D data \"{}\" to mesh \"{}\". "
1194 "You passed {} vertex indices and {} data components, but we expected {} data components ({} x {}).",
1195 dataDims, dataName, meshName,
1196 vertices.
size(), values.
size(), expectedDataSize, dataDims, vertices.
size());
1202 PRECICE_ERROR(
"Cannot write data \"{}\" to mesh \"{}\" due to invalid Vertex ID at vertices[{}]. "
1203 "Please make sure you only use the results from calls to setMeshVertex/Vertices().",
1204 dataName, meshName, *index);
1214 double relativeReadTime,
1221 PRECICE_CHECK(relativeReadTime >= 0,
"readData(...) cannot sample data before the current time.");
1222 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);
1227 "Cannot read from mesh \"{}\" after it has been reset. Please read data before calling resetMesh().",
1237 "This is typically a configuration issue of the data flow. "
1238 "Check if the data is correctly exchanged to this participant \"{}\" and mapped to mesh \"{}\".",
1242 const auto expectedDataSize = vertices.
size() * dataDims;
1244 "Input/Output sizes are inconsistent attempting to read {}D data \"{}\" from mesh \"{}\". "
1245 "You passed {} vertex indices and {} data components, but we expected {} data components ({} x {}).",
1246 dataDims, dataName, meshName,
1247 vertices.
size(), values.
size(), expectedDataSize, dataDims, vertices.
size());
1250 PRECICE_ERROR(
"Cannot read data \"{}\" from mesh \"{}\" due to invalid Vertex ID at vertices[{}]. "
1251 "Please make sure you only use the results from calls to setMeshVertex/Vertices().",
1252 dataName, meshName, *index);
1258 context.
readValues(vertices, readTime, values);
1265 double relativeReadTime,
1273 PRECICE_CHECK(relativeReadTime >= 0,
"mapAndReadData(...) cannot sample data before the current time.");
1274 PRECICE_CHECK(
isCouplingOngoing() ||
math::equals(relativeReadTime, 0.0),
"Calling mapAndReadData(...) 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);
1280 "This participant attempteded to map and read data (via \"mapAndReadData\") from mesh \"{0}\", "
1281 "but mesh \"{0}\" is either not a received mesh or its api access was not enabled in the configuration. "
1282 "mapAndReadData({0}, ...) is only valid for (<receive-mesh name=\"{0}\" ... api-access=\"true\"/>).",
1287 "The function \"mapAndReadData\" was called on mesh \"{0}\", "
1288 "but no access region was defined although this is necessary for parallel runs. "
1289 "Please define an access region using \"setMeshAccessRegion()\" before calling \"mapAndReadData()\".",
1292 PRECICE_CHECK(!
_accessor->meshContext(meshName).mesh->empty(),
"This participant tries to mapAndRead data values for data \"{0}\" on mesh \"{1}\", but the mesh \"{1}\" is empty within the defined access region on this rank. "
1293 "How should the provided data values be read? Please make sure the mesh \"{1}\" is non-empty within the access region.",
1294 dataName, meshName);
1298 "The function \"mapAndReadData\" was called on mesh \"{0}\", but no matching just-in-time mapping was configured. "
1299 "Please define a mapping in read direction from the mesh \{0}\" and omit the \"to\" attribute from the definition. "
1300 "Example \"<mapping:nearest-neighbor direction=\"read\" from=\"{0}\" constraint=\"consistent\" />",
1313 const auto nVertices = (coordinates.
size() / dim);
1321 "Input sizes are inconsistent attempting to mapAndRead {}D data \"{}\" from mesh \"{}\". "
1322 "You passed {} vertex indices and {} data components, but we expected {} data components ({} x {}).",
1323 dataDims, dataName, meshName,
1324 nVertices, values.
size(), nVertices * dataDims, dataDims, nVertices);
1340 PRECICE_CHECK(
_state ==
State::Initialized &&
isCouplingOngoing(),
"Calling writeAndMapData(...) 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 writeAndMapData(...) before the advance(...) call in your simulation loop or by using Participant::isCouplingOngoing() to implement a safeguard.");
1346 "This participant attempteded to map and read data (via \"writeAndMapData\") from mesh \"{0}\", "
1347 "but mesh \"{0}\" is either not a received mesh or its api access was not enabled in the configuration. "
1348 "writeAndMapData({0}, ...) is only valid for (<receive-mesh name=\"{0}\" ... api-access=\"true\"/>).",
1353 "The function \"writeAndMapData\" was called on mesh \"{0}\", "
1354 "but no access region was defined although this is necessary for parallel runs. "
1355 "Please define an access region using \"setMeshAccessRegion()\" before calling \"writeAndMapData()\".",
1360 "The function \"writeAndMapData\" was called on mesh \"{0}\", but no matching just-in-time mapping was configured. "
1361 "Please define a mapping in write direction to the mesh \{0}\" and omit the \"from\" attribute from the definition. "
1362 "Example \"<mapping:nearest-neighbor direction=\"write\" to=\"{0}\" constraint=\"conservative\" />",
1375 const auto nVertices = (coordinates.
size() / dim);
1382 "Input sizes are inconsistent attempting to write {}D data \"{}\" to mesh \"{}\". "
1383 "You passed {} vertex indices and {} data components, but we expected {} data components ({} x {}).",
1384 dataDims, dataName, meshName,
1385 nVertices, values.
size(), nVertices * dataDims, dataDims, nVertices);
1387 PRECICE_CHECK(!context.
mesh->
empty(),
"This participant tries to mapAndWrite data values for data \"{0}\" on mesh \"{1}\", but the mesh \"{1}\" is empty within the defined access region on this rank. "
1388 "Where should the provided data go? Please make sure the mesh \"{1}\" is non-empty within the access region.",
1389 dataName, meshName);
1415 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);
1418 PRECICE_ERROR(
"Cannot write gradient data \"{}\" to mesh \"{}\" due to invalid Vertex ID at vertices[{}]. "
1419 "Please make sure you only use the results from calls to setMeshVertex/Vertices().",
1420 dataName, meshName, *index);
1425 const auto gradientComponents = meshDims * dataDims;
1426 const auto expectedComponents = vertices.
size() * gradientComponents;
1428 "Input sizes are inconsistent attempting to write gradient for data \"{}\" to mesh \"{}\". "
1429 "A single gradient/Jacobian for {}D data on a {}D mesh has {} components. "
1430 "You passed {} vertex indices and {} gradient components, but we expected {} gradient components. ",
1432 dataDims, meshDims, gradientComponents,
1433 vertices.
size(), gradients.
size(), expectedComponents);
1449 "This participant attempteded to set an access region (via \"setMeshAccessRegion\") on mesh \"{0}\", "
1450 "but mesh \"{0}\" is either not a received mesh or its api access was not enabled in the configuration. "
1451 "setMeshAccessRegion(...) is only valid for (<receive-mesh name=\"{0}\" ... api-access=\"true\"/>).",
1461 int dim =
mesh.getDimensions();
1463 "Incorrect amount of bounding box components attempting to set the bounding box of {}D mesh \"{}\" . "
1464 "You passed {} limits, but we expected {} ({}x2).",
1465 dim, meshName, boundingBox.
size(), dim * 2, dim);
1471 for (
int d = 0; d < dim; ++d) {
1473 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...]");
1474 bounds[2 * d] = boundingBox[2 * d];
1475 bounds[2 * d + 1] = boundingBox[2 * d + 1];
1491 "This participant attempteded to get mesh vertex IDs and coordinates (via \"getMeshVertexIDsAndCoordinates\") from mesh \"{0}\", "
1492 "but mesh \"{0}\" is either not a received mesh or its api access was not enabled in the configuration. "
1493 "getMeshVertexIDsAndCoordinates(...) is only valid for (<receive-mesh name=\"{0}\" ... api-access=\"true\"/>).",
1498 "The function \"getMeshVertexIDsAndCoordinates\" was called on mesh \"{0}\", "
1499 "but no access region was defined although this is necessary for parallel runs. "
1500 "Please define an access region using \"setMeshAccessRegion()\" before calling \"getMeshVertexIDsAndCoordinates()\".",
1507 "initialize() has to be called before accessing data of the received mesh \"{}\" on participant \"{}\".",
1519 const auto meshSize = filteredVertices.size();
1522 const auto meshDims =
mesh.getDimensions();
1524 "Output size is incorrect attempting to get vertex ids of {}D mesh \"{}\". "
1525 "You passed {} vertex indices, but we expected {}. "
1526 "Use getMeshVertexSize(\"{}\") to receive the required amount of vertices.",
1527 meshDims, meshName, ids.
size(), meshSize, meshName);
1528 const auto expectedCoordinatesSize =
static_cast<unsigned long>(meshDims * meshSize);
1530 "Output size is incorrect attempting to get vertex coordinates of {}D mesh \"{}\". "
1531 "You passed {} coordinate components, but we expected {} ({}x{}). "
1532 "Use getMeshVertexSize(\"{}\") and getMeshDimensions(\"{}\") to receive the required amount components",
1533 meshDims, meshName, coordinates.
size(), expectedCoordinatesSize, meshSize, meshDims, meshName, meshName);
1535 PRECICE_ASSERT(ids.
size() <=
mesh.nVertices(),
"The queried size exceeds the number of available points.");
1537 Eigen::Map<Eigen::MatrixXd> posMatrix{
1538 coordinates.
data(),
mesh.getDimensions(),
static_cast<EIGEN_DEFAULT_DENSE_INDEX_TYPE
>(ids.
size())};
1540 for (
unsigned long i = 0; i < ids.
size(); i++) {
1541 auto localID = filteredVertices[i].get().getID();
1544 posMatrix.col(i) = filteredVertices[i].get().getCoords();
1553 return lhs->mesh->getName() < rhs->mesh->getName();
1557 if (meshContext->provideMesh)
1558 meshContext->mesh->computeBoundingBox();
1560 meshContext->clearMappings();
1564 meshContext->partition->compareBoundingBoxes();
1574 auto &contexts =
_accessor->usedMeshContexts();
1576 std::sort(contexts.begin(), contexts.end(),
1578 return lhs->mesh->getName() < rhs->mesh->getName();
1582 meshContext->partition->communicate();
1589 for (
auto &m2nPair :
_m2ns) {
1590 if (m2nPair.second.m2n->usesTwoLevelInitialization()) {
1599 [](
MeshContext const *
const meshContext) ->
bool {
1600 return meshContext->provideMesh;
1605 meshContext->partition->compute();
1606 if (not meshContext->provideMesh) {
1607 meshContext->mesh->computeBoundingBox();
1610 meshContext->mesh->allocateDataValues();
1612 const auto requiredSize = meshContext->mesh->nVertices();
1613 for (
auto &context :
_accessor->writeDataContexts()) {
1614 if (context.getMeshName() == meshContext->mesh->getName()) {
1615 context.resizeBufferTo(requiredSize);
1624 bool anyMappingChanged =
false;
1626 if (not context.mapping->hasComputedMapping()) {
1628 "Automatic RBF mapping alias from mesh \"{}\" to mesh \"{}\" in \"{}\" direction resolves to \"{}\" .",
1629 context.mapping->getInputMesh()->getName(), context.mapping->getOutputMesh()->getName(), mappingType, context.mapping->getName());
1630 PRECICE_INFO(
"Computing \"{}\" mapping from mesh \"{}\" to mesh \"{}\" in \"{}\" direction.",
1631 context.mapping->getName(), context.mapping->getInputMesh()->getName(), context.mapping->getOutputMesh()->getName(), mappingType);
1632 context.mapping->computeMapping();
1633 anyMappingChanged =
true;
1636 if (anyMappingChanged) {
1637 _accessor->initializeMappingDataCache(mappingType);
1650 for (
auto &context :
_accessor->writeDataContexts()) {
1651 if (context.hasMapping()) {
1652 PRECICE_DEBUG(
"Map initial write data \"{}\" from mesh \"{}\"", context.getDataName(), context.getMeshName());
1667 for (
auto &context :
_accessor->writeDataContexts()) {
1668 if (context.hasMapping()) {
1669 PRECICE_DEBUG(
"Map write data \"{}\" from mesh \"{}\"", context.getDataName(), context.getMeshName());
1678 for (
auto &context :
_accessor->readDataContexts()) {
1679 if (context.hasMapping()) {
1684 context.clearToDataFor(fromData);
1686 context.trimToDataAfterFor(fromData, startOfTimeWindow);
1701 for (
auto &context :
_accessor->readDataContexts()) {
1702 if (context.hasMapping()) {
1703 PRECICE_DEBUG(
"Map initial read data \"{}\" to mesh \"{}\"", context.getDataName(), context.getMeshName());
1719 for (
auto &context :
_accessor->readDataContexts()) {
1720 if (context.hasMapping()) {
1721 PRECICE_DEBUG(
"Map read data \"{}\" to mesh \"{}\"", context.getDataName(), context.getMeshName());
1764 for (
auto &context :
_accessor->writeDataContexts()) {
1766 context.resetBufferedData();
1773 const auto &partConfig = *
config.getParticipantConfiguration();
1775 "This participant's name, which was specified in the constructor of the preCICE interface as \"{}\", "
1776 "is not defined in the preCICE configuration. "
1777 "Please double-check the correct spelling.",
1805 "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 {}.",
1806 secondaryRank, dt, computedTimeStepSize);
1818 [[maybe_unused]]
auto remoteChanges1 =
_couplingScheme->firstSynchronization(localChanges);
1821 [[maybe_unused]]
auto remoteChanges2 =
_couplingScheme->secondSynchronization();
1834 for (
auto &iter :
_m2ns) {
1835 auto bm2n = iter.second;
1836 if (!bm2n.m2n->isConnected()) {
1837 PRECICE_DEBUG(
"Skipping closure of defective connection with {}", bm2n.remoteName);
1841 auto comm = bm2n.m2n->getPrimaryRankCommunication();
1842 PRECICE_DEBUG(
"Synchronizing primary rank with {}", bm2n.remoteName);
1843 if (bm2n.isRequesting) {
1844 comm->send(ping, 0);
1846 comm->receive(receive, 0);
1850 comm->receive(receive, 0);
1852 comm->send(pong, 0);
1856 PRECICE_DEBUG(
"Closing distributed communication with {}", bm2n.remoteName);
1857 bm2n.m2n->closeDistributedConnections();
1859 PRECICE_DEBUG(
"Closing communication with {}", bm2n.remoteName);
1860 bm2n.m2n->closeConnection();
1873 return *
_accessor->usedMeshContext(meshName).mesh;
1894 for (
auto context :
_accessor->usedMeshContexts()) {
1897 PRECICE_DEBUG(
"Mesh changes of rank: {}", localMeshChanges);
1905 PRECICE_DEBUG(
"Mesh changes of participant: {}", totalMeshChangesInt);
1906 return totalMeshChangesInt;
1911 auto meshContexts =
_accessor->usedMeshContexts();
1913 if (totalMeshChanges[i] > 0.0) {
1914 meshContexts[i]->mesh->clearDataStamples();
1926 PRECICE_DEBUG(
"Remeshing is{} required by this participant.", (requestReinit ?
"" :
" not"));
1928 bool swarmReinitRequired = requestReinit;
1929 for (
auto &iter :
_m2ns) {
1930 PRECICE_DEBUG(
"Coordinating remeshing with {}", iter.first);
1931 bool received =
false;
1932 auto &comm = *iter.second.m2n->getPrimaryRankCommunication();
1933 if (iter.second.isRequesting) {
1934 comm.send(requestReinit, 0);
1935 comm.receive(received, 0);
1937 comm.receive(received, 0);
1938 comm.send(requestReinit, 0);
1940 swarmReinitRequired |= received;
1942 PRECICE_DEBUG(
"Coordinated that overall{} remeshing is required.", (swarmReinitRequired ?
"" :
" no"));
1945 return swarmReinitRequired;
1947 bool swarmReinitRequired =
false;
1949 return swarmReinitRequired;
1956 "The provided section name \"{}\" may not contain a forward-slash \"/\"",
#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(...)
int getDimensions() const
void clear()
Removes all mesh elements and data values (does not remove data or the bounding boxes).
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 empty() const
Does the mesh contain any vertices?
Main class for preCICE XML configuration tree.
@ 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 hasJustInTimeMapping() const
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
std::deque< profiling::Event > _userEvents
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.
MeshChanges getTotalMeshChanges() const
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 clearStamplesOfChangedMeshes(MeshChanges totalMeshChanges)
Clears stample of changed meshes to make them consistent after the reinitialization.
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.
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.
bool reinitHandshake(bool requestReinit) const
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.
void mapInitialReadData()
void handleExports(ExportTiming timing)
~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 setMeshVertices(std::string_view meshName, ::precice::span< const double > positions, ::precice::span< VertexID > ids)
Creates multiple mesh vertices.
void resetMesh(std::string_view meshName)
std::vector< int > MeshChanges
How many ranks have changed each used mesh.
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 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
void reinitialize()
Reinitializes preCICE.
void setupWatcher()
Setup mesh watcher such as WatchPoints.
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.
std::string _configHash
The hash of the configuration file used to configure this participant.
void setupCommunication()
Connect participants including repartitioning.
bool _allowsRemeshing
Are experimental remeshing API calls allowed?
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 startProfilingSection(std::string_view eventName)
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.
void mapAndReadData(std::string_view meshName, std::string_view dataName, ::precice::span< const double > coordinates, double relativeReadTime, ::precice::span< double > values) const
Reads data values from a mesh using a just-in-time data mapping. Values correspond to a given point i...
std::unique_ptr< profiling::Event > _solverAdvanceEvent
bool requiresUserDefinedAccessRegion(std::string_view meshName) const
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 writeAndMapData(std::string_view meshName, std::string_view dataName, ::precice::span< const double > coordinates, ::precice::span< const double > values)
Writes data values to a mesh using a just-in-time mapping (experimental).
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.
void stopLastProfilingSection()
Stores one Data object with related mesh. Context stores data to be read from and potentially provide...
bool hasSamples() const
Are there samples to read from?
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.
void mapAndReadValues(::precice::span< const double > coordinates, double readTime, ::precice::span< double > values)
Forwards the just-in-time mapping API call for reading data to the data context.
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 writeAndMapValues(::precice::span< const double > coordinates, ::precice::span< const double > values)
Forwards the just-in-time mapping API call for writing data to the data context.
void writeValuesIntoDataBuffer(::precice::span< const VertexID > vertices, ::precice::span< const double > values)
Store values in _writeDataBuffer.
Container and creator for meshes.
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.
void addData(std::string_view key, int value)
Adds named integer data, associated to an event.
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 void allreduceSum(precice::span< const double > sendData, precice::span< double > rcvData)
static bool isPrimary()
True if this process is running the primary rank.
static void broadcast(bool &value)
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.
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.
T current_path(T... args)
contains actions to modify exchanged data.
std::unique_ptr< Action > PtrAction
std::shared_ptr< WatchPoint > PtrWatchPoint
std::string errorInvalidVertexID(int vid)
static constexpr auto errorInvalidVertexIDRange
std::shared_ptr< ParticipantState > PtrParticipant
std::shared_ptr< WatchIntegral > PtrWatchIntegral
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::size_t countVerticesInBoundingBox(mesh::PtrMesh mesh, const mesh::BoundingBox &bb)
Given a Mesh and a bounding box, counts all vertices within the bounding box.
static constexpr Group API
Convenience instance of the Cat::API.
static constexpr SynchronizeTag Synchronize
Convenience instance of the SynchronizeTag.
static constexpr Group Fundamental
Convenience instance of the Cat::Fundamental.
contains the time interpolation logic.
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.
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={})
auto make_array(Elements &&...elements) -> std::array< typename std::common_type< Elements... >::type, sizeof...(Elements)>
Function that generates an array from given elements.
std::string 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.
void checkVerticesInsideAccessRegion(precice::span< const double > coordinates, const int meshDim, std::string_view functionName) const
std::shared_ptr< mesh::BoundingBox > userDefinedAccessRegion
std::vector< std::reference_wrapper< const mesh::Vertex > > filterVerticesToLocalAccessRegion(bool requiresBB) const
Tightly coupled to the parameters of Participant()