Skip to content

[WIP] Add Python code for couple your code section #523

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions css/customstyles-precice.css
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,14 @@ div#tg-sb-sidebar {
div#tg-sb-sidebar {
position: static;
}
/* style navtabs */
.post-content ol li, .post-content ul li {
margin: 0px;
}
div.tab-content {
padding: 0px;
background-color: white;
}
div.tab-content div.tab-pane pre {
margin-top: 0px;
}
53 changes: 52 additions & 1 deletion css/printstyles.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ a[href^="http:"]::after, a[href^="https:"]::after, a[href^="ftp:"]::after {
a[href] {
color: #0A76BB !important;
}
a[href*="mailto"]::after, a[data-toggle="tooltip"]::after, a[href].noCrossRef::after {
a[href*="mailto"]::after, a[data-toggle="tooltip"]::after, a[href].noCrossRef::after, a[data-toggle="tab"]::after {
content: "";
}

Expand Down Expand Up @@ -219,4 +219,55 @@ pre > code {
h1[id], h2[id], h3[id], h4[id], h5[id], h6[id], dt[id] {
padding-top: 1.5em;
margin-top: -1em;
}

/* prepare nav tabs for printing */
.nav > li.active > a, /* tab headers */
.nav > li > a {
color: black;
background-color: white;
border: 1px solid #ccc;
border-radius: 4px 4px 0 0;
}
.tab-content > .tab-pane {
display: block !important; /* display non-active panes */
position: relative;
}
div.tab-content div.tab-pane pre {
margin-top: 1em;
}
/* create counters to link tab headers to tab contents */
.post-content ul.nav.nav-tabs {
counter-reset: tab_number; /* creates a new instance of counter with name tab_number */
}
.post-content .nav.nav-tabs li::after {
counter-increment: tab_number; /* increment counter */
content: counter(tab_number); /* display value in small bubble */
position: absolute;
top: -1em;
left: -1em;
padding: 2px 5px;
background-color: white;
color: black;
font-size: 0.65em;
border-radius: 50%;
border: 1px solid #ccc;
box-shadow: 1px 1px 1px grey;
}
div.tab-content {
counter-reset: pane_number;
}
div.tab-pane::after {
counter-increment: pane_number;
content: counter(pane_number);
position: absolute;
top: -1em;
left: -1em;
padding: 2px 5px;
background-color: white;
color: black;
font-size: 0.65em;
border-radius: 50%;
border: 1px solid #ccc;
box-shadow: 1px 1px 1px gray;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ For surface coupling in 2D, mesh connectivity boils down to defining edges betwe
For volume coupling in 2D, mesh connectivity boils down to defining triangles and / or quads between vertices. In 3D, you need to define tetrahedra introduced in version `2.5.0`.

All kind of connectivity can be built up directly from vertices. Triangles and quads also allow us to define them using edge IDs.
<ul id="apiTabs" class="nav nav-tabs">
<li class="active"><a href="#cpp-1" data-toggle="tab">C++</a></li>
<li><a href="#python-1" data-toggle="tab">Python</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="cpp-1" markdown="1">

```cpp
void setMeshEdge(precice::string_view meshName, VertexID firstVertexID, VertexID secondVertexID);
Expand All @@ -22,7 +28,25 @@ void setMeshQuad(precice::string_view meshName, VertexID firstVertexID, VertexID
void setMeshTetrahedron(precice::string_view meshName, VertexID firstVertexID, VertexID secondVertexID, VertexID thirdVertexID, VertexID fourthVertexID);
```

</div>
<div role="tabpanel" class="tab-pane" id="python-1" markdown="1">

```python
set_mesh_edge(mesh_name, first_vertex_id, second_vertex_id)
set_mesh_triangle(mesh_name, first_vertex_id, second_vertex_id, third_vertex_id)
set_mesh_quad(mesh_name, first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id)
set_mesh_tetrahedron(mesh_name, first_vertex_id, second_vertex_id, third_vertex_id, fourth_vertex_id)
```

</div>
</div>
There are also bulk versions of these methods, which can be easier to handle in some cases:
<ul id="apiTabs" class="nav nav-tabs">
<li class="active"><a href="#cpp-2" data-toggle="tab">C++</a></li>
<li><a href="#python-2" data-toggle="tab">Python</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="cpp-2" markdown="1">

```cpp
void setMeshEdges(precice::string_view meshName, precice::span<const VertexID> vertices);
Expand All @@ -31,12 +55,39 @@ void setMeshQuads(precice::string_view meshName, precice::span<const VertexID> v
void setMeshTetrahedra(precice::string_view meshName, precice::span<const VertexID> vertices);
```

</div>
<div role="tabpanel" class="tab-pane" id="python-2" markdown="1">

```python
set_mesh_edges(mesh_name, vertices)
set_mesh_triangles(mesh_name, vertices)
set_mesh_quads(mesh_name, vertices)
set_mesh_tetrahedra(mesh_name, vertices)
```

</div>
</div>
If you do not configure any features in the preCICE configuration that require mesh connectivity, all these API functions are [no-ops](https://en.wikipedia.org/wiki/NOP_(code)). Thus, don't worry about performance. If you need a significant workload to already create this connectivity information in your adapter in the first place, you can also explicitly ask preCICE whether it is required:
<ul id="apiTabs" class="nav nav-tabs">
<li class="active"><a href="#cpp-3" data-toggle="tab">C++</a></li>
<li><a href="#python-3" data-toggle="tab">Python</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="cpp-3" markdown="1">

```cpp
bool requiresMeshConnectivityFor(precice::string_view meshName);
```

</div>
<div role="tabpanel" class="tab-pane" id="python-3" markdown="1">

```python
requires_mesh_connectivity_for(mesh_name)
```

</div>
</div>
{% warning %}
The API function `isMeshConnectivityRequired` is only supported since v2.3.
{% endwarning %}
Expand All @@ -52,6 +103,12 @@ Quads are only supported since v2.1. For older version, the methods only exist a
{% endwarning %}

The following code shows how mesh connectivity can be defined in our example. For sake of simplification, let's only define one triangle and let's assume that it consists of the first three vertices.
<ul id="apiTabs" class="nav nav-tabs">
<li class="active"><a href="#cpp-4" data-toggle="tab">C++</a></li>
<li><a href="#python-4" data-toggle="tab">Python</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="cpp-4" markdown="1">

```cpp
/* ... */
Expand Down Expand Up @@ -83,6 +140,30 @@ if (precice.requiresMeshConnectivityFor(meshName)) {
/* ... */
```

</div>
<div role="tabpanel" class="tab-pane" id="python-4" markdown="1">

```python
# We define the unit square in 2D
coords = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
vertex_ids = precice.set_mesh_vertices(mesh_name, coords)

if precice.requires_mesh_connectivity_for(mesh_name):

# Define triangles ABC and BCD separately
precice.set_mesh_triangle(mesh_name, vertex_ids[0], vertex_ids[1], vertex_ids[2])
precice.set_mesh_triangle(mesh_name, vertex_ids[1], vertex_ids[2], vertex_ids[3])

# Define triangles in one go
triangles = np.array([
[vertex_ids[0], vertex_ids[1], vertex_ids[2]],
[vertex_ids[1], vertex_ids[2], vertex_ids[3]]
])
precice.set_mesh_triangles(mesh_name, triangles)
```

</div>
</div>
## Mesh pre-processing

preCICE pre-processes all provided meshes during initialization, removing duplicates and adding missing hierarchical elements.
Expand All @@ -109,6 +190,12 @@ In this case you can save a mapping from Solver ID to preCICE Vertex ID, after d
When iterating over the faces, get the vertex identifiers of defining points.
For triangular faces, these would be the 3 corner points.
Then map these Solver IDs to preCICE IDs, and use those to define your connectivity.
<ul id="apiTabs" class="nav nav-tabs">
<li class="active"><a href="#cpp-5" data-toggle="tab">C++</a></li>
<li><a href="#python-5" data-toggle="tab">Python</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="cpp-5" markdown="1">

```cpp
Participant participant(...);
Expand All @@ -131,6 +218,30 @@ for (auto& tri: solver.triangularFaces) {
}
```

</div>
<div role="tabpanel" class="tab-pane" id="python-5" markdown="1">

```python
participant = precice.Participant(...)

id_maps = dict()
for vertex in solver.vertices:
vertex_id = participant.set_mesh_vertex("MyMesh", vertex.coords)
# Set the vertex_id as label
id_maps[vertex._id] = vertex_id

for tri in solver.triangular_faces:
# Lookup the precice vertex id using solver vertex id
a = id_maps.get(tri.a._id)
b = id_maps.get(tri.b._id)
c = id_maps.get(tri.c._id)

participant.set_mesh_triangle(mesh_name, a, b, c)
```

</div>
</div>

### Solver supports custom attributes

You solver doesn't provide a unique identifier for each vertex.
Expand All @@ -145,6 +256,12 @@ Examples of such attributes:
In this case you can save preCICE Vertex IDs as labels directly in the solver vertices.
Define the vertices using the preCICE API, then iterate over them and apply the preCICE vertex IDs as labels.
When iterating over faces, get the preCICE vertex IDs from the point labels, and use those to define your connectivity.
<ul id="apiTabs" class="nav nav-tabs">
<li class="active"><a href="#cpp-6" data-toggle="tab">C++</a></li>
<li><a href="#python-6" data-toggle="tab">Python</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="cpp-6" markdown="1">

```cpp
Participant participant(...);
Expand All @@ -164,6 +281,27 @@ for (auto& tri: solver.triangularFaces) {
}
```

</div>
<div role="tabpanel" class="tab-pane" id="python-6" markdown="1">

```python
participant = precice.Participant(...)

for vertex in solver.vertices:
vertex_id = participant.set_mesh_vertex("MyMesh", vertex.coords)
vertex.label = vertex_id

for tri in solver.triangular_faces:
a = tri.a.label
b = tri.b.label
c = tri.c.label

participant.set_mesh_triangle("MyMesh", a, b, c)
```

</div>
</div>

### Solver supports coordinates only

Your solver provides coordinates only or labels are already used for another purpose.
Expand All @@ -173,6 +311,12 @@ Depending on your solver, coordinates available at various stages may be subject
Hence, a C++ `std::map` without custom comparator, or python `dict` may not be sufficient.

An alternative would be to use a spatial index as a data structure to store this information.
<ul id="apiTabs" class="nav nav-tabs">
<li class="active"><a href="#cpp-7" data-toggle="tab">C++</a></li>
<li><a href="#python-7" data-toggle="tab">Python</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="cpp-7" markdown="1">

```cpp
Participant participant(...);
Expand Down Expand Up @@ -224,6 +368,8 @@ class IDLookup {
};
```

</div>
<div role="tabpanel" class="tab-pane" id="python-7" markdown="1">
In python, you could use the rtree package:

```py
Expand All @@ -242,3 +388,6 @@ for tri in solver.triangularFaces:
c = index.nearest(tri.c.coords)
participant.set_mesh_triangle("MyMesh", a, b, c)
```

</div>
</div>
Loading