|
59 | 59 | "cell_type": "code",
|
60 | 60 | "execution_count": 3,
|
61 | 61 | "metadata": {},
|
62 |
| - "outputs": [], |
| 62 | + "outputs": [ |
| 63 | + { |
| 64 | + "data": { |
| 65 | + "text/plain": [ |
| 66 | + "1" |
| 67 | + ] |
| 68 | + }, |
| 69 | + "execution_count": 3, |
| 70 | + "metadata": {}, |
| 71 | + "output_type": "execute_result" |
| 72 | + } |
| 73 | + ], |
63 | 74 | "source": [
|
64 | 75 | "gdim = 2\n",
|
65 |
| - "status = gmsh.model.addPhysicalGroup(gdim, [membrane], 1)" |
| 76 | + "gmsh.model.addPhysicalGroup(gdim, [membrane], 1)" |
66 | 77 | ]
|
67 | 78 | },
|
68 | 79 | {
|
|
83 | 94 | "text": [
|
84 | 95 | "Info : Meshing 1D...\n",
|
85 | 96 | "Info : Meshing curve 1 (Ellipse)\n",
|
86 |
| - "Info : Done meshing 1D (Wall 0.000161882s, CPU 0.000254s)\n", |
| 97 | + "Info : Done meshing 1D (Wall 0.000842374s, CPU 0.000939s)\n", |
87 | 98 | "Info : Meshing 2D...\n",
|
88 | 99 | "Info : Meshing surface 1 (Plane, Frontal-Delaunay)\n",
|
89 |
| - "Info : Done meshing 2D (Wall 0.0748596s, CPU 0.075328s)\n", |
| 100 | + "Info : Done meshing 2D (Wall 0.0902373s, CPU 0.088198s)\n", |
90 | 101 | "Info : 1550 nodes 3099 elements\n"
|
91 | 102 | ]
|
92 | 103 | }
|
|
101 | 112 | "cell_type": "markdown",
|
102 | 113 | "metadata": {},
|
103 | 114 | "source": [
|
104 |
| - "We will import the GMSH-mesh directly from GMSH, using the approach in Section 2 of [A GMSH tutorial for DOLFINx](https://jsdokken.com/src/tutorial_gmsh.html). To make sure this runs in parallel and serial, we will read in the mesh on one processor, and let DOLFINx distribute the mesh data among the processros." |
| 115 | + "# Interfacing with GMSH in DOLFINx\n", |
| 116 | + "We will import the GMSH-mesh directly from GMSH, using the `dolfinx.io.gmshio` interface in DOLFINx.\n", |
| 117 | + "As we in the example have not specified which process we have created the gmsh model on, a model has been created on each mpi process. However, we would like to be able to use a mesh distributed over all processes. We therefore take the model generated on rank 0 of `MPI.COMM_WORLD`, and distribute it over all available ranks. We will also get two mesh tags, one for cells marked with physical groups in the mesh and one for facets marked with physical groups. As we did not not add any physical groups of dimension `gdim-1`, there will be no entities in the `facet_markers`." |
105 | 118 | ]
|
106 | 119 | },
|
107 | 120 | {
|
|
110 | 123 | "metadata": {},
|
111 | 124 | "outputs": [],
|
112 | 125 | "source": [
|
113 |
| - "from dolfinx import io\n", |
| 126 | + "from dolfinx.io import gmshio\n", |
114 | 127 | "from mpi4py import MPI\n",
|
115 |
| - "if MPI.COMM_WORLD.rank == 0:\n", |
116 |
| - " # Get mesh geometry\n", |
117 |
| - " geometry_data = io.extract_gmsh_geometry(gmsh.model)\n", |
118 |
| - " # Get mesh topology for each element\n", |
119 |
| - " topology_data = io.extract_gmsh_topology_and_markers(gmsh.model)" |
120 |
| - ] |
121 |
| - }, |
122 |
| - { |
123 |
| - "cell_type": "markdown", |
124 |
| - "metadata": {}, |
125 |
| - "source": [ |
126 |
| - "The topology data is a dictionary, where the key is the gmsh cell type (an integer). Each key accesses a dictionary with the topology data and corresponding topology markers. As this mesh only contains one cell type (triangles), as we did not mark any facets, we do not need to loop over the keys of this dictionary, only extract the first one." |
127 |
| - ] |
128 |
| - }, |
129 |
| - { |
130 |
| - "cell_type": "code", |
131 |
| - "execution_count": 6, |
132 |
| - "metadata": {}, |
133 |
| - "outputs": [], |
134 |
| - "source": [ |
135 |
| - "import numpy as np\n", |
136 |
| - "if MPI.COMM_WORLD.rank == 0:\n", |
137 |
| - " # Extract the cell type and number of nodes per cell and broadcast\n", |
138 |
| - " # it to the other processors \n", |
139 |
| - " gmsh_cell_type = list(topology_data.keys())[0] \n", |
140 |
| - " properties = gmsh.model.mesh.getElementProperties(gmsh_cell_type)\n", |
141 |
| - " name, dim, order, num_nodes, local_coords, _ = properties\n", |
142 |
| - " cells = topology_data[gmsh_cell_type][\"topology\"]\n", |
143 |
| - " cell_id, num_nodes = MPI.COMM_WORLD.bcast([gmsh_cell_type, num_nodes], root=0)\n", |
144 |
| - "else: \n", |
145 |
| - " cell_id, num_nodes = MPI.COMM_WORLD.bcast([None, None], root=0)\n", |
146 |
| - " cells, geometry_data = np.empty([0, num_nodes]), np.empty([0, gdim])" |
147 |
| - ] |
148 |
| - }, |
149 |
| - { |
150 |
| - "cell_type": "markdown", |
151 |
| - "metadata": {}, |
152 |
| - "source": [ |
153 |
| - "As we have now broadcasted all the information required to distribute the mesh in parallel" |
154 |
| - ] |
155 |
| - }, |
156 |
| - { |
157 |
| - "cell_type": "code", |
158 |
| - "execution_count": 7, |
159 |
| - "metadata": {}, |
160 |
| - "outputs": [], |
161 |
| - "source": [ |
162 |
| - "from dolfinx import mesh, cpp\n", |
163 |
| - "# Permute topology data from MSH-ordering to dolfinx-ordering\n", |
164 |
| - "ufl_domain = io.ufl_mesh_from_gmsh(cell_id, gdim)\n", |
165 |
| - "gmsh_cell_perm = io.cell_perm_gmsh(cpp.mesh.to_type(str(ufl_domain.ufl_cell())), num_nodes)\n", |
166 |
| - "cells = cells[:, gmsh_cell_perm]\n", |
167 | 128 | "\n",
|
168 |
| - "# Create distributed mesh\n", |
169 |
| - "domain = mesh.create_mesh(MPI.COMM_WORLD, cells, geometry_data[:, :gdim], ufl_domain)" |
| 129 | + "gmsh_model_rank = 0\n", |
| 130 | + "mesh_comm = MPI.COMM_WORLD\n", |
| 131 | + "domain, cell_markers, facet_markers = gmshio.model_to_mesh(gmsh.model, mesh_comm, gmsh_model_rank, gdim=gdim)" |
170 | 132 | ]
|
171 | 133 | },
|
172 | 134 | {
|
|
178 | 140 | },
|
179 | 141 | {
|
180 | 142 | "cell_type": "code",
|
181 |
| - "execution_count": 8, |
| 143 | + "execution_count": 6, |
182 | 144 | "metadata": {},
|
183 | 145 | "outputs": [],
|
184 | 146 | "source": [
|
|
196 | 158 | },
|
197 | 159 | {
|
198 | 160 | "cell_type": "code",
|
199 |
| - "execution_count": 9, |
| 161 | + "execution_count": 7, |
200 | 162 | "metadata": {},
|
201 | 163 | "outputs": [],
|
202 | 164 | "source": [
|
|
218 | 180 | },
|
219 | 181 | {
|
220 | 182 | "cell_type": "code",
|
221 |
| - "execution_count": 10, |
| 183 | + "execution_count": 8, |
222 | 184 | "metadata": {},
|
223 | 185 | "outputs": [],
|
224 | 186 | "source": [
|
| 187 | + "import numpy as np\n", |
225 | 188 | "def on_boundary(x):\n",
|
226 | 189 | " return np.isclose(np.sqrt(x[0]**2 + x[1]**2), 1)\n",
|
227 | 190 | "boundary_dofs = fem.locate_dofs_geometrical(V, on_boundary)"
|
|
236 | 199 | },
|
237 | 200 | {
|
238 | 201 | "cell_type": "code",
|
239 |
| - "execution_count": 11, |
| 202 | + "execution_count": 9, |
240 | 203 | "metadata": {},
|
241 | 204 | "outputs": [],
|
242 | 205 | "source": [
|
|
253 | 216 | },
|
254 | 217 | {
|
255 | 218 | "cell_type": "code",
|
256 |
| - "execution_count": 12, |
| 219 | + "execution_count": 10, |
257 | 220 | "metadata": {},
|
258 | 221 | "outputs": [],
|
259 | 222 | "source": [
|
|
276 | 239 | },
|
277 | 240 | {
|
278 | 241 | "cell_type": "code",
|
279 |
| - "execution_count": 13, |
| 242 | + "execution_count": 11, |
280 | 243 | "metadata": {},
|
281 | 244 | "outputs": [],
|
282 | 245 | "source": [
|
|
296 | 259 | },
|
297 | 260 | {
|
298 | 261 | "cell_type": "code",
|
299 |
| - "execution_count": 14, |
| 262 | + "execution_count": 12, |
300 | 263 | "metadata": {
|
301 | 264 | "scrolled": true
|
302 | 265 | },
|
303 | 266 | "outputs": [
|
| 267 | + { |
| 268 | + "name": "stderr", |
| 269 | + "output_type": "stream", |
| 270 | + "text": [ |
| 271 | + "\u001b[0m\u001b[2m2022-07-15 17:30:39.952 ( 0.525s) [ 76AC1000] vtkExtractEdges.cxx:435 INFO| \u001b[0mExecuting edge extractor: points are renumbered\u001b[0m\n", |
| 272 | + "\u001b[0m\u001b[2m2022-07-15 17:30:39.958 ( 0.531s) [ 76AC1000] vtkExtractEdges.cxx:551 INFO| \u001b[0mCreated 4521 edges\u001b[0m\n" |
| 273 | + ] |
| 274 | + }, |
304 | 275 | {
|
305 | 276 | "data": {
|
306 | 277 | "application/vnd.jupyter.widget-view+json": {
|
307 |
| - "model_id": "b0f7b49211fa49ddafd2bcb0e28e0fc7", |
| 278 | + "model_id": "32d8b1feff23457cb167bf0dc36d7ab8", |
308 | 279 | "version_major": 2,
|
309 | 280 | "version_minor": 0
|
310 | 281 | },
|
|
347 | 318 | },
|
348 | 319 | {
|
349 | 320 | "cell_type": "code",
|
350 |
| - "execution_count": 15, |
| 321 | + "execution_count": 13, |
351 | 322 | "metadata": {},
|
352 | 323 | "outputs": [
|
353 | 324 | {
|
354 | 325 | "data": {
|
355 | 326 | "application/vnd.jupyter.widget-view+json": {
|
356 |
| - "model_id": "9620c7a85a8c480f8afe9cd768fe9969", |
| 327 | + "model_id": "1f73d1fd610047b7b68f4ebd6375eec0", |
357 | 328 | "version_major": 2,
|
358 | 329 | "version_minor": 0
|
359 | 330 | },
|
|
392 | 363 | },
|
393 | 364 | {
|
394 | 365 | "cell_type": "code",
|
395 |
| - "execution_count": 16, |
| 366 | + "execution_count": 14, |
396 | 367 | "metadata": {},
|
397 | 368 | "outputs": [],
|
398 | 369 | "source": [
|
|
415 | 386 | },
|
416 | 387 | {
|
417 | 388 | "cell_type": "code",
|
418 |
| - "execution_count": 17, |
| 389 | + "execution_count": 15, |
419 | 390 | "metadata": {},
|
420 | 391 | "outputs": [],
|
421 | 392 | "source": [
|
|
437 | 408 | },
|
438 | 409 | {
|
439 | 410 | "cell_type": "code",
|
440 |
| - "execution_count": 18, |
| 411 | + "execution_count": 16, |
441 | 412 | "metadata": {},
|
442 | 413 | "outputs": [],
|
443 | 414 | "source": [
|
|
462 | 433 | },
|
463 | 434 | {
|
464 | 435 | "cell_type": "code",
|
465 |
| - "execution_count": 19, |
| 436 | + "execution_count": 17, |
466 | 437 | "metadata": {},
|
467 | 438 | "outputs": [],
|
468 | 439 | "source": [
|
|
480 | 451 | },
|
481 | 452 | {
|
482 | 453 | "cell_type": "code",
|
483 |
| - "execution_count": 20, |
| 454 | + "execution_count": 18, |
484 | 455 | "metadata": {},
|
485 | 456 | "outputs": [
|
486 | 457 | {
|
|
518 | 489 | },
|
519 | 490 | {
|
520 | 491 | "cell_type": "code",
|
521 |
| - "execution_count": 21, |
| 492 | + "execution_count": 19, |
522 | 493 | "metadata": {},
|
523 | 494 | "outputs": [],
|
524 | 495 | "source": [
|
|
0 commit comments