This tutorial is presented as Python code running inside a Jupyter Notebook, the recommended way to use Salvus. To run it yourself you can copy/type each individual cell or directly download the full notebook, including all required files.

Meshing cylindrical domains

Several applications require a cylindrical geometry, for instance, to model boreholes, pipelines or the tissue/bone structure of the human limbs. In the simplest case, a cylindrical medium can be described by a 1D radial model, which is then extruded in the third dimension.
SalvusProject currently has no built-in support for such meshes, however, we can utilize external meshing tools. This mini tutorial shows how to create such meshes and how to add them to a project.
import salvus.namespace as sn
import numpy as np
import os

SALVUS_FLOW_SITE_NAME = os.environ.get("SITE_NAME", "local")
PROJECT_DIR = "project"
In this example, we model a cylindrical domain that mimics a steel pipe filled and surrounded by water. We use a dominant frequency of 5 kHz and a vertical extent of 1 m.
v_min = 1500.0
elements_per_wavelength = 4.0
frequency_in_hertz = 5e3
length_in_meters = 1.0

Mesh creation

The mesh generation proceeds in two steps. First, we create a disk-shaped 2D mesh that includes the radial model. In a second step, the mesh is extruded along the longitudinal axis. The radial profile can be specified as a bm file, which contains the material model as well as interfaces.
We consider a steel pipe with an inner diameter of 20 cm and a thickness of 2 cm, which is submerged in water. The mesh generation algorithm will automatically extract fluid and solid parts of the domain, and adjust the element size to the slowest velocity.
NAME         radial_model
UNITS        m
COLUMNS      radius rho vp vs
    0.0   1000.0     2000.0       0.0
    0.1   1000.0     2000.0       0.0
    0.1   7710.0     5890.0    3240.0
    0.12  7710.0     5890.0    3240.0
    0.12  1000.0     2000.0       0.0
    0.5   1000.0     2000.0       0.0

High-order shape transformations

Salvus supports different polynomial orders for the shape transformations of the quadrilateral or hexahedral elements. This is particularly useful when meshing curved domain, where a piecewise (bi-)linear transformation could result in a poorly approximated shape. This parameter is called tensor_order within the Salvus ecosystem, and applies to both the polynomial degree of the model as well as the shape transformation.
To demonstrate the difference, we will take a quick detour and generate two meshes for a frequency of 2 kHz and with tensor_order of 1 and 4, respectively.
mc = sn.simple_mesh.Circular2D()
mc.basic.model = ""
mc.basic.min_period_in_seconds = 1 / 2e3
mc.basic.elements_per_wavelength = elements_per_wavelength
<salvus.mesh.data_structures.unstructured_mesh.unstructured_mesh.UnstructuredMesh object at 0x7f30d1d90f10>
We notice that the coarse mesh poorly models the concentric shape of the 1D model. Note that the element-size is chosen according to resolve the desired frequency at the specified number of elements per wavelength. However, the predominant numerical error is introduced by the poor approximation of the geometry.
When changing the tensor order to 4, the edges of the elements are defined by 4th-order Lagrange polynomials, which results in a much better shape.
mc.advanced.tensor_order = 4
mesh = mc.create_mesh()