Skip to content

Documentation for mesh generation

create_concrete_slab(point1, point2, n_x, n_y, margin, s, msh_filename, xdmf_filenames, z)

This function creates a 3D-quadrilateral mesh in the shape of a cuboid with reinforcement rebars as line elements in a 3D space. Only a very general case with a uniform rebar-grid at the top and/or bottom of the slab is possible.

Parameters:

Name Type Description Default
point1 ArrayLike

Starting point of the cuboid.

required
point2 ArrayLike

Endpoint of the cuboid.

required
n_x int

Number of reinforcement bars in x-direction.

required
n_y int

Number of reinforcement bars in y-direction.

required
margin float

Absolute value of the smallest distance between the outer edges of the concrete mesh and a reinforcement element.

required
s float

Maximal element size. It may be corrected according to n_x and n_y, such that the reinforcement discretization is always held true and reinorcement&concrete elements share the same nodes.

required
msh_filename str

Filename of the mesh (msh file).

required
xdmf_filenames list[str]

Desired names of the two xdmf meshes (concrete & reinforcement).

required
z list[float]

Position of the reinforecement bar(s). The list may contain either one or two floats, dictating whether one or two reinforcement bars should be created. The float represents the z-coordinate of the bar(s)

required
Source code in reinforcement/mesh.py
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
def create_concrete_slab(
    point1: ArrayLike,
    point2: ArrayLike,
    n_x: int,
    n_y: int,
    margin: float,
    s: float,
    msh_filename: str,
    xdmf_filenames: list[str],
    z: list[float],
):
    """
    This function creates a 3D-quadrilateral mesh in the shape of a cuboid with reinforcement
    rebars as line elements in a 3D space. Only a very general case with a uniform rebar-grid
    at the top and/or bottom of the slab is possible.

    Args:

        point1: 
            Starting point of the cuboid.
        point2: 
            Endpoint of the cuboid.
        n_x: 
            Number of reinforcement bars in x-direction.
        n_y: 
            Number of reinforcement bars in y-direction.
        margin: 
            Absolute value of the smallest distance between the outer edges of the concrete mesh
            and a reinforcement element.
        s: 
            Maximal element size. It may be corrected according to n_x and n_y, such that
            the reinforcement discretization is always held true and reinorcement&concrete
            elements share the same nodes.
        msh_filename: 
            Filename of the mesh (msh file).
        xdmf_filenames: 
            Desired names of the two xdmf meshes (concrete & reinforcement).
        z: 
            Position of the reinforecement bar(s). The list may contain either one or two floats, dictating whether one or two reinforcement bars should be created. The float represents the z-coordinate of the bar(s)

    Returns:


    """

    x0, y0, z0 = point1
    l, w, h = point2

    # initialize gmsh
    gmsh.initialize()

    # alias to facilitate code writing
    mymesh = gmsh.model
    gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 100000)
    # create the first point
    point1 = mymesh.occ.addPoint(x0, y0, z0)
    mymesh.occ.synchronize()

    concrete_elems_x = _num_elems(int((l - 2 * margin) / s), n_x - 1)
    concrete_elems_y = _num_elems(int((w - 2 * margin) / s), n_y - 1)
    n_elements_margin = math.ceil(margin / s)

    # evaluate z, find correct margins and amount of elements in z-direction
    if len(z) == 2:
        n_elements_margin_z_1 = math.ceil(z[0] / s)
        n_elements_margin_z_2 = math.ceil((h - z[1]) / s)
        heights_z = [z[0] / h, z[1] / h, 1]
        numElements_z = [
            n_elements_margin_z_1,
            int((h - (z[0] + (h - z[1]))) / s),
            n_elements_margin_z_2,
        ]

    elif len(z) == 1:
        n_elements_margin_z_1 = math.ceil(z[0] / s)
        n_elements_margin_z_2 = math.ceil((h - z[0]) / s)
        heights_z = [z[0] / h, 1]
        numElements_z = [n_elements_margin_z_1, n_elements_margin_z_2]

    # extrude three times, point -> line (x-direction), line -> rectangle (y-direction), rectangle -> cuboid (z-direction)
    mymesh.occ.extrude(
        [(0, point1)],
        l,
        0,
        0,
        numElements=[n_elements_margin, concrete_elems_x, n_elements_margin],
        heights=[margin / l, 1 - margin / l, 1],
        recombine=True,
    )
    mymesh.occ.synchronize()

    mymesh.occ.extrude(
        [(1, 1)],
        0,
        w,
        0,
        numElements=[n_elements_margin, concrete_elems_y, n_elements_margin],
        heights=[margin / w, 1 - margin / w, 1],
        recombine=True,
    )
    mymesh.occ.synchronize()

    mymesh.occ.extrude(
        [(2, 1)],
        0,
        0,
        h,
        numElements=numElements_z,
        heights=heights_z,
        recombine=True,
    )
    mymesh.occ.synchronize()

    # add volume as physical group
    mymesh.addPhysicalGroup(dim=3, tags=[1], tag=1)
    mymesh.occ.synchronize()

    # add points and lines where reinforcement is to be added
    x = np.linspace(x0 + margin, l - margin, concrete_elems_x + 1)
    y = np.linspace(y0 + margin, w - margin, concrete_elems_y + 1)
    reinf_tags, reinf_tags_2 = _reinforcement_points(n_x, n_y, x, y, True, z, margin)

    # add lines connecting all reinforcement nodes and save their tags
    line_tags = _reinforcement_lines(
        reinf_tags, reinf_tags_2, n_x, n_y, concrete_elems_x, concrete_elems_y
    )

    # add new points to mesh by synchronizing
    mymesh.occ.synchronize()

    # add all reinforcement lines to a physical group
    mymesh.addPhysicalGroup(dim=1, tags=line_tags, tag=1)
    mymesh.occ.synchronize()

    # now generate the 3D-mesh
    meshFact = gmsh.model.mesh
    meshFact.generate(3)

    # Save mesh as msh file
    gmsh.write(msh_filename)
    gmsh.finalize()

    # create two xdmf files (concrete & reinforcement)
    _create_xdmf(msh_filename, xdmf_filenames)

read_xdmf(xdmf_files)

Function that reads xdmf_files to use them in FEniCSx

Parameters:

Name Type Description Default
xdmf_files list[str]

Names (str) of the xdmf_files, [concrete, reinforcement] - in this order.

required

Returns:

Name Type Description
concrete_mesh dfx.mesh.Mesh

The concrete mesh (hexa elements).

rebar_mesh dfx.mesh.Mesh

The reinforcement mesh (line elements).

Source code in reinforcement/mesh.py
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
def read_xdmf(xdmf_files : list[str]) -> tuple[dfx.mesh.Mesh, dfx.mesh.Mesh]:
    """
    Function that reads xdmf_files to use them in FEniCSx

    Args:
        xdmf_files:
            Names (str) of the xdmf_files, [concrete, reinforcement] - in this order.

    Returns:
        concrete_mesh: 
            The concrete mesh (hexa elements).
        rebar_mesh: 
            The reinforcement mesh (line elements).

    """
    with dfx.io.XDMFFile(MPI.COMM_WORLD, xdmf_files[0], "r") as xdmf:
        concrete_mesh = xdmf.read_mesh(name="Grid")

    with dfx.io.XDMFFile(MPI.COMM_WORLD, xdmf_files[1], "r") as xdmf:
        rebar_mesh = xdmf.read_mesh(name="Grid")
    return concrete_mesh, rebar_mesh