Domain#

When configuring a simulation, one of the first things required is to define the domain. What is considered here by domain is:

  • Domain size for the simulation

  • Bodies in this volume

  • Refinements to apply in the volume

Domain size#

The domain size for the simulation is the volume in which the simulation will run.

simulations:
  - name: example
    domain:
      # All dimensions in domain_size MUST BE divisible by block_size
      domain_size:
        x: 96
        y: 80
        z: 128
      # Rescale domain for output
      # pos_rescaled = pos * scale + translation
      domain_rescale:
        translation: [0, 0, 0]
        scale: [1, 1, 1]
      # Leave it as 8
      block_size: 8

Note

Currently the simulation volume supports only a box (2D or 3D)

The domain is divided in blocks that are boxes with size block_size. These blocks can be refined recursively, which generate nodes that have half the distance between them. The higher the level, the more refined it is, with level 0 being the domain with no refinement.

Blocks communicate with each other through neighbours on the same level, or with their parent/children of different level.

Important

All dimensions in the domain_size must be divisible by block_size.

For the block size, there is a limitation between it and the shared memory size of the GPU. It’s recommended to leave it as 8, because most GPUs will be able to run the simulation with this size.

It’s possible to rescale the domain. This is useful for changing system coordinates, from LBM to meters, for example. This can be done through the domain_rescale field.

Bodies#

For the bodies inside the domain the field domain.bodies is used

simulations:
  - name: example
    domain:
      bodies:
        # Body named CAARC
        CAARC:
          # IBM configurations
          IBM:
            # True to run this body
            # Defaults to true
            run: True
            # IBM configuration name, at `models.IBM.cfgs.{cfg_name}`
            # Defaults to "default"
            cfg_use: cfg_name
            # IBM order for forces interpolation spread
            # Bodies in same order have forces calculated at the same time (don't affect each other)
            # Forces are computed from smaller to bigger order, similar to how BC is done
            # Defaults to 0
            order: 0
            # Interval in time steps in which to run IBM
            # When end step or start step is zero, they're not applied
            # Defaults to {end_step: 0, start_step: 0} (full simulation)
            interval_run:
              end_step: 0
              start_step: 0
          # Path to .lnas file for geometry
          lnas_path: fixture/lnas/wind_tunnel/CAARC.lnas
          # The min max area for the triangles to use (considering lvl 0)
          # bigger triangles are refined until reach the level area
          # smaller triangles are treated as `small_triangles`
          # `max` should be at least 4 times`the `min` size
          # Defaults to { min: 0.25, max: 1 }
          area: { min: 0.25, max: 1 }
          # Treatment triangles for small triangles
          # error: raises an error if they exists
          # add: adds the small triangles
          # ignore: ignore the small triangles
          # Defaults to error
          small_triangles: "error" # | "add" | "remove"
          # Volumes limit, remove triangles outside it in each geometry step
          # Defaults to no limit (no triangle is removed)
          volumes_limits:
            # These volumes are before any transformation in the body
            raw:
              - start: [10, 20, 0]
                end: [100, 100, 100]
            # These are applied after the body's transformations
            body_transformed:
              - start: [60, 40, 0]
                end: [100, 200, 100]
            # These are applied after all transformations are applied
            full_transformed: 
              - start: [60, 40, 0]
                end: [100, 200, 100]
              - start: [100, 40, 50]
                end: [150, 140, 70]
          # Transformations to apply in the body
          # For more information check the `transformations` section
          # Defaults to no transformation
          transformation:
            fixed_point: [0, 0, 0]
            # Rotation is in radians
            rotation: [0, 0, 0]
            scale: [1.0, 1.0, 1.0]
            translation: [12.0, 0.0, 1.0]
        # Another body, the only required field is lnas_path, all others are optional
        cube:
          lnas_path: fixture/lnas/basic/cube.lnas
      # Domain limits for effect of bodies in the domain
      # (i.e. There are no IBM nodes outside this volume)
      bodies_domain_limits:
        start: [8.0, 4.0, 0.0]
        end: [448.0, 156.0, 48.0]
        # Defaults to true
        is_abs: true

Important

The body uses a .lnas file for the geometry specification. The geometry consists of a series of triangles and vertices, which are used and processed in multiple ways.

The file also have a list of surfaces that are defined by a series of triangles in the geometry. This surfaces may be used for multiple purposes as well.

Point Cloud#

For specification of point clouds the field domain.point_cloud is used

simulations:
  - name: example
    domain:
      point_cloud:
        # Point cloud named TreeCloud
        TreeCloud:
          # IBM configurations, same from bodies, to specify IBM to run
          IBM:
            run: True
            cfg_use: cfg_name
            order: 0
            interval_run:
              end_step: 0
              start_step: 0
          # Path to .csv file for point cloud
          # Must have keys: [x, y, z, nx, ny, nz, area]
          csv_path: fixture/point_cloud/tree.csv
          # Transformation to apply in the point cloud
          # For more information check the `transformations` section
          # Defaults to no transformation
          transformation:
            fixed_point: [0, 0, 0]
            # Rotation is in radians
            rotation: [0, 0, 0]
            scale: [1.0, 1.0, 1.0]
            translation: [12.0, 0.0, 1.0]
          # Another body, the only required field is lnas_path, all others are optional
          another_point_cloud:
            csv_path: fixture/point_cloud/cube.csv

Transformations#

It’s possible to apply transformations to the bodies. The operations that we support are:

  • Scaling

  • Rotation

  • Translation

These are all linear transformations that are applied sequentially. There is also an important aspect which is the fixed point, that defined the point in which the geometry is scaled and rotated in relation to.

The full order of transformations is:

  1. Translate body to centralize at (0, 0, 0) the fixed point

  2. Apply scale transformation

  3. Apply rotation transformation

  4. Apply translation transformation

  5. Revert the translation done in step 1

For more informations and specifications on how this is done, check the LNAS repository.

Domain Refinement#

For the domain refinement specification, the domain.refinement field is used

simulations:
  - name: example
    domain:
      refinement:
        static:
          # Refining a volume
          volume_refine:
            # List of volumes to refine
            volumes_refine:
              # The volume specification and level to refine.
              # It's possible to use a relative volume by specifying is_abs: False
              # By default is_abs defauls to true
              # All blocks inside these volumes are refined
              - lvl: 1
                start: [0.0, 0.0, 0.0]
                end: [32.0, 160.0, 64.0]
                # Defaults to true
                is_abs: true
                
          # Refining a body
          body_refine:
            bodies:
              # Bodies to refine
              - body_name: CAARC
                # Level to use
                lvl: 4
                # Normals offset to refine 
                # This offsets the vertices in normal direction multiplying by the offset
                # and refines this body. All blocks that the body is in are refined
                normal_offsets: !range [-0.5, 2.1, 0.5]
              # It's possible to specify only a surface of the body for usage too
              - body_name: CAARC.surface_name
                lvl: 4
                normal_offsets: !math [1/4]
                # Transformation to apply to body for transformation
                transformation:
                  translation: [0.0, 0.0, -1.0]
                  fixed_point: [0, 0, 0]
                  rotation: [0, 0, 0]
                  scale: [1.0, 1.0, 1.0]
          # Limiting the volume for refinement
          limit_volume:
            bodies:
              - body_name: CAARC
                lvl: 6
                normal_offsets: [0, 1]
            # This limits the volume that can be refined by all refinemets (volume and body)
            volume_refinement_limit:
              start: [0, 10, 0]
              end: [40, 50, 150]
              # Defaults to true
              is_abs: true
          # Ignoring volumes 
          ignore_volumes:
            bodies:
              - body_name: CAARC
                lvl: 6 
                normal_offsets: !range [-0.5, 5, 0.2]
            # List of volumes to not refine. 
            # If a block is fully inside any of these volumes it's not refined
            volumes_not_refine:
              - start: [0, 10, 0]
                end: [40, 50, 150]
                # Defaults to true
                is_abs: true
              - start: [0, 0.15, 0.1]
                end: [0.1, 0.2, 0.3]
          # Example using all cases presented above
          full_example:
            volumes_refine:
              - is_abs: true
                lvl: 1
                start: [0.0, 0.0, 0.0]
                end: [32.0, 160.0, 64.0]
              - is_abs: true
                lvl: 4
                start: [10, 20, 30]
                end: [32.0, 160.0, 64.0]
            bodies:
              - body_name: CAARC
                lvl: 6
                normal_offsets: [-0.1, 0, 0.1]
            volume_refinement_limit:
              is_abs: true
              start: [0, 10, 0]
              end: [40, 50, 150]
            volumes_not_refine:
              - is_abs: true
                start: [0, 10, 0]
                end: [40, 50, 150]
              - is_abs: false
                start: [0, 0.15, 0.1]
                end: [0.1, 0.2, 0.3]

Important

The refinement follows some rules, one important is that blocks that “communicate” with each other are at most one level difference. So when specifying a volume to refine up to level 2, the blocks in the limit of this volume will be at level 1.

Global transformations#

When considering a change of scale, rotation of domain or change of perspective, it’s common to apply these in multiple geometries and entities in the domain. For this we provide the field global_transformations, that allows the user to apply the same transformation to multiple entities.

      global_transformations:
        # List of transformations to apply
        - transformation:
            translation: [0, 10, 3.6]
          point_clouds_apply: ["tree", "one_sponge"]
          bodies_apply: ["CAARC"]
          probes_apply:
            [
              "series.series1.lines",
              "series.series1.points.point1",
              "series.another_series",
              "spectrum.downstream",
            ]
          # True to apply this transformation to bodies in series as well
          apply_to_bodies_probes: false
        # Another transformation
        - transformation:
            fixed_point: [608.90625, 64, 0]
            rotation: [0, 0, 3.141592654]
            scale: [1, 1, 1]
          point_clouds_aply: []
          bodies_apply: ["CAARC"]
          probes_apply: []

It’s possible to define a list of transformations to apply for a list of bodies and probes. These are applied after the body specific ones and in sequence to each other. So in the example above, first the translation is applied to the body and the probes and only after that the body is rotated. The same rules serves for the probes.

Note

To know more about probes, check their section in data.

For the probes, it’s possible to select a series of probes in it. Say the transformation must be applied to all lines in the series called series1. We can specify it using the series.series1.lines. But if we want to apply it only to a single line called my_line, we’re able to do it using series.series1.lines.my_line. Same applies to transform all geometries in a series or other fields such as bodies, points or csvs.

To transform spectrum points the rule is the same, using spectrum.point_name to transform a point with the given name, or simply spectrum to apply to all spectrum points.