Skip to content

Commit 86caace

Browse files
committed
Expanded geometry tutorial
1 parent 3adbf7d commit 86caace

2 files changed

Lines changed: 108 additions & 23 deletions

File tree

README.md

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,16 @@
22

33
*Start solving PDEs in Julia*
44

5-
65
| **Documentation** |
76
|:------------ |
87
| [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://gridap.github.io/Tutorials/stable) [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://gridap.github.io/Tutorials/dev) |
98
|**Build Status** |
109
| [![Build Status](https://github.com/gridap/Tutorials/workflows/CI/badge.svg?branch=master)](https://github.com/gridap/Tutorials/actions?query=workflow%3ACI) |
1110
| **Community** |
12-
| [![Join the chat at https://gitter.im/Gridap-jl/community](https://badges.gitter.im/Gridap-jl/community.svg)](https://gitter.im/Gridap-jl/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) |
11+
| [![Join the chat at https://gitter.im/Gridap-jl/community](https://badges.gitter.im/Gridap-jl/community.svg)](https://gitter.im/Gridap-jl/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat in Slack](https://img.shields.io/badge/chat-on_slack-purple?style=flat&logo=slack&logoColor=white)(https://julialang.slack.com/archives/C02AK382QSG)]|
1312
| **Citation** |
1413
| [![DOI](https://joss.theoj.org/papers/10.21105/joss.02520/status.svg)](https://doi.org/10.21105/joss.02520) |
1514

16-
17-
18-
1915
## What
2016

2117
This repo contains a set of tutorials to learn how to solve partial differential equations (PDEs) in Julia with the Gridap ecosystem of packages. At the root of this ecosystem is the [Gridap.jl](https://github.com/gridap/Gridap.jl) library. The initial tutorials illustrate the usage of the tools in [Gridap.jl](https://github.com/gridap/Gridap.jl), and these are the tutorials new users should focus on.
@@ -35,7 +31,7 @@ Visit one of the following pages, depending of your needs, and start enjoying!
3531
- [**STABLE**](https://gridap.github.io/Tutorials/stable) — **Tutorials for the most recently tagged version of Gridap.jl.**
3632
- [**DEVEL**](https://gridap.github.io/Tutorials/dev) — *Tutorials for the in-development version of Gridap.jl.*
3733

38-
## Generating tutorials locally
34+
## Generating tutorials locally
3935

4036
Note: **only if you intend to contribute to the tutorials as an advanced user/developer**
4137

@@ -55,12 +51,11 @@ and then, each time that you perform a change on the tutorial sources, you have
5551
julia --project=docs docs/make.jl # From the Unix shell, located at the root of Tutorials repo
5652
```
5753

58-
to generate the tutorials. The files generated are available at `Tutorials/docs/build/`.
59-
54+
to generate the tutorials. The files generated are available at `Tutorials/docs/build/`.
6055

6156
## Gridap community
6257

63-
Join to our [gitter](https://gitter.im/Gridap-jl/community) chat to ask questions and interact with the Gridap community.
58+
Join to our [gitter](https://gitter.im/Gridap-jl/community) or [slack](https://julialang.slack.com/archives/C02AK382QSG) chats to ask questions and interact with the Gridap community.
6459

6560
## How to cite Gridap
6661

@@ -83,7 +78,4 @@ In order to give credit to the `Gridap` contributors, we simply ask you to cite
8378

8479
## Contact
8580

86-
8781
Please, contact the project administrators, [Santiago Badia](mailto:santiago.badia@monash.edu) and [Francesc Verdugo](mailto:fverdugo@cimne.upc.edu), for further questions about licenses and terms of use.
88-
89-

src/geometry_dev.jl

Lines changed: 104 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ using Plots
2626
# We begin by defining helper functions that will be essential throughout this tutorial.
2727
# These functions help us visualize and work with our mesh structures.
2828

29-
# Convert a CartesianDiscreteModel to an UnstructuredDiscreteModel for more generic handling
29+
# Convert a `CartesianDiscreteModel` to an `UnstructuredDiscreteModel` for more generic handling.
3030
function cartesian_model(args...; kwargs...)
3131
UnstructuredDiscreteModel(CartesianDiscreteModel(args...; kwargs...))
3232
end
3333

34-
# Visualization function to plot nodes with their IDs
35-
# Input: node_coords - Array of node coordinates
36-
# node_ids - Array of corresponding node IDs
34+
# Visualization function to plot nodes with their IDs. Input:
35+
# - node_coords: Array of node coordinates.
36+
# - node_ids: Array of corresponding node IDs.
3737
function plot_node_numbering(node_coords, node_ids)
3838
x = map(c -> c[1], node_coords)
3939
y = map(c -> c[2], node_coords)
@@ -43,8 +43,8 @@ function plot_node_numbering(node_coords, node_ids)
4343
vline!(unique(y), linestyle=:dash, color=:grey)
4444
end
4545

46-
# Overloaded method to plot node numbering directly from a model
47-
# This function extracts the necessary information from the model and calls the base plotting function
46+
# Overloaded method to plot node numbering directly from a model.
47+
# This function extracts the necessary information from the model and calls the base plotting function.
4848
function plot_node_numbering(model)
4949
D = num_cell_dims(model)
5050
topo = get_grid_topology(model)
@@ -83,15 +83,15 @@ end
8383
#
8484
# ### Key Concept: Nodes vs. Vertices
8585
#
86-
# One of the most important distinctions in Gridap is between nodes and vertices:
86+
# A very important distinction in Gridap is between nodes and vertices:
8787
#
8888
# - **Vertices** (Topological entities):
8989
# * 0-dimensional entities in the `GridTopology`
9090
# * Define the connectivity of the mesh
9191
# * Used for neighbor queries and mesh traversal
9292
# * Number of vertices depends only on topology
9393
#
94-
# - **Nodes** (Geometric entities):
94+
# - **Nodes** (Geometrical entities):
9595
# * Control points stored in the `Grid`
9696
# * Define the geometry of elements
9797
# * Used for interpolation and mapping
@@ -180,10 +180,10 @@ node_coordinates = get_node_coordinates(grid) # Physical coordinates of nodes
180180
#
181181
# There are two ways to get the coordinates of nodes for each cell:
182182
#
183-
# 1. Using standard Julia mapping:
183+
# A) Using standard Julia mapping:
184184
cell_to_node_coords = map(nodes -> node_coordinates[nodes], cell_to_nodes)
185185

186-
# 2. Using Gridap's lazy evaluation system (more efficient for large meshes):
186+
# B) Using Gridap's lazy evaluation system (more efficient for large meshes):
187187
cell_to_node_coords = lazy_map(Broadcasting(Reindex(node_coordinates)),cell_to_nodes)
188188

189189
# ### Geometric Mappings
@@ -230,7 +230,7 @@ writevtk(new_grid,"half_cylinder_linear")
230230
# our half-cylinder looks faceted. This is because we're still using linear elements
231231
# (straight edges) to approximate the curved geometry.
232232
#
233-
# ### Solution: High-order Elements
233+
# ### Example: High-order Elements
234234
#
235235
# To accurately represent curved geometries, we need high-order elements:
236236

@@ -389,3 +389,96 @@ mobius = UnstructuredDiscreteModel(grid,topo,labels)
389389
# Visualize the vertex numbering:
390390
plot_node_numbering(mobius)
391391
# ![](../assets/geometry/mobius.png)
392+
393+
# ## FaceLabelings and boundary conditions
394+
#
395+
# The `FaceLabeling` component of a `DiscreteModel` is the way Gridap handles boundary conditions.
396+
# The basic idea is that, similar to Gmsh, we classify the d-faces (cells, faces, edges, nodes) of the mesh
397+
# into different entities (physical groups in Gmsh terminology) which in turn have one or more
398+
# tags/labels associated with them.
399+
# We can then query the `FaceLabeling` for the tags associated with a given d-face,
400+
# or the d-faces associated with a given tag.
401+
#
402+
# We will now explore ways to create and manipulate `Facelabeling` objects.
403+
#
404+
# ### Creating FaceLabelings
405+
#
406+
# The simplest way to create a blank `FaceLabeling` is to use your `GridTopology`:
407+
#
408+
409+
model = cartesian_model((0,1,0,1),(3,3))
410+
topo = get_grid_topology(model)
411+
412+
labels = FaceLabeling(topo)
413+
414+
# The above `FaceLabeling` is by default created with 2 entities and 2 tags, associated to
415+
# interior and boundary d-faces respectively. The boundary facets are chosen as the ones
416+
# with a single neighboring cell.
417+
#
418+
# We can extract the low-level information from the `FaceLabeling` object:
419+
420+
tag_names = get_tag_name(labels) # Each name is a string
421+
tag_entities = get_tag_entities(labels) # For each tag, a vector of entities
422+
cell_to_entity = get_face_entity(labels,2) # For each cell, its associated entity
423+
edge_to_entity = get_face_entity(labels,1) # For each edge, its associated entity
424+
node_to_entity = get_face_entity(labels,0) # For each node, its associated entity
425+
426+
# It is usually more convenient to visualise it in Paraview by exporting to vtk:
427+
428+
writevtk(model,"labels_basic",labels=labels)
429+
430+
# Another useful way to create a `FaceLabeling` is by providing a coloring for the mesh cells,
431+
# where each color corresponds to a different tag.
432+
# The d-faces of the mesh will have all the tags associated to the cells that share them.
433+
434+
cell_to_tag = [1,1,1,2,2,3,2,2,3]
435+
tag_to_name = ["A","B","C"]
436+
labels_cw = Geometry.face_labeling_from_cell_tags(topo,cell_to_tag,tag_to_name)
437+
writevtk(model,"labels_cellwise",labels=labels_cw)
438+
439+
# We can also create a `FaceLabeling` from a vertex filter. The resulting `FaceLabeling` will have
440+
# only one tag, gathering the d-faces whose vertices ALL fullfill `filter(x) == true`.
441+
442+
filter(x) = abs(x[1]- 1.0) < 1.e-5
443+
labels_vf = Geometry.face_labeling_from_vertex_filter(topo, "top", filter)
444+
writevtk(model,"labels_filter",labels=labels_vf)
445+
446+
# `FaceLabeling` objects can also be merged together. The resulting `FaceLabeling` will have
447+
# the union of the tags and entities of the original ones.
448+
# Note that this modifies the first `FaceLabeling` in place.
449+
450+
labels = merge!(labels, labels_cw, labels_vf)
451+
writevtk(model,"labels_merged",labels=labels)
452+
453+
# ### Creating new tags from existing ones
454+
#
455+
# Tags in a `FaceLabeling` support all the usual set operation, i.e union, intersection,
456+
# difference and complementary.
457+
458+
cell_to_tag = [1,1,1,2,2,3,2,2,3]
459+
tag_to_name = ["A","B","C"]
460+
labels = Geometry.face_labeling_from_cell_tags(topo,cell_to_tag,tag_to_name)
461+
462+
# Union: Takes as input a list of tags and creates a new tag that is the union of all of them.
463+
Geometry.add_tag_from_tags!(labels,"A∪B",["A","B"])
464+
465+
# Intersection: Takes as input a list of tags and creates a new tag that is the intersection of all of them.
466+
Geometry.add_tag_from_tags_intersection!(labels,"A∩B",["A","B"])
467+
468+
# Complementary: Takes as input a list of tags and creates a new tag that is the complementary of the union.
469+
Geometry.add_tag_from_tags_complementary!(labels,"!A",["A"])
470+
471+
# Set difference: Takes as input two lists of tags (tags_include - tags_exclude)
472+
# and creates a new tag that contains all the d-faces that are in the first list but not in the second.
473+
Geometry.add_tag_from_tags_setdiff!(labels,"A-B",["A"],["B"]) # set difference
474+
475+
writevtk(model,"labels_setops",labels=labels)
476+
477+
# ### FaceLabeling queries
478+
#
479+
# The most common way of query information from a `FaceLabeling` is to query a face mask for
480+
# a given tag and face dimension. If multiple tags are provided, the union of the tags is returned.
481+
482+
face_dim = 1
483+
mask = get_face_mask(labels,["A","C"],face_dim) # Boolean mask
484+
ids = findall(edges_mask_A) # Edge IDs

0 commit comments

Comments
 (0)