PeriHub Model Documentation

Introduction

This document provides a guide on how to write a Python file that defines your own model in PeriHub.

Model Definition and Imports

The following is a basic structure for defining a model in Python:

"""
title: NAME OF YOUR MODEL
description: DESCRIPTION OF YOUR MODEL
author: YOUR USERNAME
requirements: PIP REQUIREMENTS
version: 0.1.0
"""
import numpy as np
from pydantic import BaseModel, Field

from ...support.model.geometry import Geometry

Valves Class

The following is a basic structure for defining a class that represents valves in the model. You can define as much valves as you need. Theses will be represented in the frontend under the Model section.

class Valves(BaseModel):
    FLOAT: float = Field(
        default=10.5,
        title="FLOAT",
        description="FLOAT",
    )
    BOOLEAN: bool = Field(
        default=True,
        title="BOOLEAN",
        description="BOOLEAN",
    )

Main Class

The following is a basic structure for defining a class that represents the main model. The first function is the constructor of the class, here you can define the variables that will be used in the model. Availabe variables are the valves as well as the two_dimensional parameter.

class main:
    def __init__(self, valves, two_dimensional):
        self.FLOAT = valves["FLOAT"]

The second function is the get_discretization function, here you can define the discretization of the model. The discretization is a list of three floats that represent the discretization in the x, y and z directions.

def get_discretization(self):
    disc = [self.FLOAT, self.FLOAT, self.FLOAT]
    self.disc = disc
    return disc

The third function is the create_geometry function, here you can define the geometry of the model. For basic shapes you can use the Geometry class. The function returns the x, y and z values of the geometry.

def create_geometry(self):
    geo = Geometry()

    x_values, y_values, z_values = geo.create_rectangle(
        coor=[
            self.FLOAT,
            self.FLOAT,
            self.FLOAT,
            self.FLOAT,
            self.FLOAT,
            self.FLOAT,
        ],
        dx_value=self.disc,
    )
    return x_values, y_values, z_values

The last function is the crate_block_definition function, here you can define the blocks of the model. The function returns an array of block ids. Input values are the x, y and z values of the geometry, as well as the default block id array with all values set to 1.

def crate_block_definition(self, x_values, y_values, z_values, k):
    """doc"""
    k = np.where(
        x_values >= self.FLOAT,
        2,
        k,
    )
    return k

Optionally, you can the edit_model_data function, here you can change any values of the model retrieved from PeriHub.

def edit_model_data(self, model_data):
    model_data.bondFilters[0].lowerLeftCornerX = self.FLOAT
    return model_data

Full Example

"""
title: Kalthoff-Winkler
description: Crack propagation
author: Jan-Timo Hesse
requirements:
version: 0.1.0
"""
import numpy as np
from pydantic import BaseModel, Field

from ...support.model.geometry import Geometry


class Valves(BaseModel):
    DISCRETIZATION: float = Field(
        default=100,
        title="Discretization",
        description="Discretization",
    )
    LENGTH: float = Field(
        default=100,
        title="Length",
        description="Length",
    )
    HEIGHT: float = Field(
        default=200,
        title="Height",
        description="Height",
    )
    WIDTH: float = Field(
        default=10,
        title="Width",
        description="Width",
    )

class main:
    def __init__(self, valves, twoDimensional):
        self.xbegin = 0
        self.xend = valves["LENGTH"]
        self.ybegin = -valves["HEIGHT"] / 2
        self.yend = valves["HEIGHT"] / 2
        self.discretization = valves["DISCRETIZATION"]

        if twoDimensional:
            self.zbegin = 0
            self.zend = 0
        else:
            self.zbegin = -valves["WIDTH"] / 2
            self.zend = valves["WIDTH"] / 2

    def get_discretization(self):
        number_nodes = 2 * int(self.discretization / 2) + 1
        disc = [
            self.yend / number_nodes,
            self.yend / number_nodes,
            self.yend / number_nodes,
        ]
        self.disc = disc
        return disc

    def create_geometry(self):
        """doc"""

        geo = Geometry()

        x_values, y_values, z_values = geo.create_rectangle(
            coor=[
                self.xbegin,
                self.xend,
                self.ybegin,
                self.yend,
                self.zbegin,
                self.zend,
            ],
            dx_value=self.disc,
        )

        return (
            x_values,
            y_value,
            z_values,
        )

    def crate_block_definition(self, x_values, y_values, z_values, k):
        """doc"""
        k = np.where(
            np.logical_and(
                x_values < self.disc[0] * 5,
                np.logical_and(y_values <= 25, y_values >= -25),
            ),
            2,
            k,
        )
        k = np.where(
            np.logical_and(
                x_values < self.disc[0],
                np.logical_and(y_values <= 25, y_values >= -25),
            ),
            3,
            k,
        )
        return k

Copyright © 2024 German Aerospace Center (DLR) — PeriHub | Jan-Timo Hesse | Christian Willberg