Overview
This tutorial introduces one alternative for effectively interacting with a Kratos simulation to modify some of its parameters and observe the effect of such a modification on the results in real-time. Admittedly, this can be achived for any of the simulations available in Kratos, however, it is particularly suitable for fast simulations, like the ones achived by using Reduced Order Models ROM. Therefore, this tutorial focuses on an example using the RomApplication. The Python module vedo is used for the interactive visualization.
Content
What is vedo?
(vedo) is a lightweight and powerful python module for scientific analysis and visualization of 3D objects. It is based on numpy and VTK, with no other dependencies.
Installation
The following section guides the user toward the setting up of the Kratos applications and installation of vedo to run the example case.
This example uses an earlier version of the vedo module. Therefore, please install using the command provided below, and not the one for the latest version of vedo in vedo’s repository.
# installing earlier version of vedo (previously known as vtkplotter)
pip3 install vtkplotter==2020.0.1
Make sure to install the applications required. In this example the RomApplication and the StructuralMechanicsApplication are used. Therefore, add both these application to the Kratos configure file.
Linux:
add_app ${KRATOS_APP_DIR}/StructuralMechanicsApplication
add_app ${KRATOS_APP_DIR}/RomApplication
Windows:
CALL :add_app %KRATOS_APP_DIR%/StructuralMechanicsApplication
CALL :add_app %KRATOS_APP_DIR%/RomApplication
How to use vedo for interacting with the simulation
In this section, a simple example is used to illustrate the approach taken to interactively modify the parameters of a simulation in Kratos. Download the files for this example here .
Problem definition
A static structural example has been chosen for demonstrating the integration of vedo into the simulation. The selected geometry is the Stanford bunny. As can be seen, displacement constraints are being applied to the base and a varying pressure is applied to the face of the bunny.
The original model from which this Reduced Order Model was obtained contained 30.000 elements, therefore it was too slow for solving it in real time. On the other hand, the ROM only requires the evaluation of 50 elements to obtain the results.
Integration of vedo
Thanks to the Python interface of Kratos, the vedo module can be used by simply calling it inside a derived class in the original MainKratos.py.
We start now analyzing how vedo is defined inside our code. First of all we observe the import statement (notice vedo’s old version is called vtkplotter):
#Import visualization tool
import vtkplotter
In order to change the magnitude of the load applied, we will use an on-screen slider; for which we define the slider class. Notice that we are going to apply this pressure in MPa, but Kratos is expecting a pressure in Pa, therefore we take into account the 1e6 factor here.
#Slider class
class Slider():
def __init__(self, InitialValue):
self.value = InitialValue
def GenericSlider(self,widget, event):
value = widget.GetRepresentation().GetValue()*1e6
self.value = value
Inside a class derived from StructuralMechanicsAnalysisROM and which we have called InteractiveSimulation in this example, we define the Plotter object as an attribute of InteractiveSimulation. Moreover we add to it the slider for modifying the pressure.
self.slider1 = Slider(0)
self.Plot = vtkplotter.Plotter(title="Simulation Results",interactive=False)
self.Plot.addSlider2D(self.slider1.GenericSlider, -200, 400 , value = 0, pos=3, title="Pressure (MPa)")
The method ApplyBoundaryConditions will capture the current position of the slider before each solve step, and will apply the corresponding pressure to the simulation by employing the AssignScalarVariableToConditionsProcess.
def ApplyBoundaryConditions(self):
super().ApplyBoundaryConditions()
Pressure = self.slider1.value
print(f'Pressure is {Pressure} Pa')
PressureSettings = KratosMultiphysics.Parameters("""
{
"model_part_name" : "Structure.COMPUTE_HROM.SurfacePressure3D_Pressure_on_surfaces_Auto4",
"variable_name" : "POSITIVE_FACE_PRESSURE",
"interval" : [0.0,"End"]
}
"""
)
PressureSettings.AddEmptyValue("value").SetDouble(Pressure)
AssignScalarVariableToConditionsProcess(self.model, PressureSettings).ExecuteInitializeSolutionStep()
Vedo allows the definition of generic buttons to perform some action on the visualization. For this example, we define 2 buttons: for pausing-continuing and for stoping the simulation.
self.PauseButton = self.Plot.addButton(
self.PauseButtonFunc,
pos=(0.9, .9), # x,y fraction from bottom left corner
states=["PAUSE", "CONTINUE"],
c=["w", "w"],
bc=["b", "g"], # colors of states
font="courier", # arial, courier, times
size=25,
bold=True,
italic=False,
)
self.StopButton = self.Plot.addButton(
self.StopButtonFunc,
pos=(0.1, .9), # x,y fraction from bottom left corner
states=["STOP"],
c=["w"],
bc=["r"], # colors of states
font="courier", # arial, courier, times
size=25,
bold=True,
italic=False,
)
def PauseButtonFunc(self):
vtkplotter.printc(self.PauseButton.status(), box="_", dim=True)
if self.PauseButton.status() == "PAUSE":
self.Plot.interactive = True
else:
self.Plot.interactive = False
self.PauseButton.switch() # change to next status
def StopButtonFunc(self):
vtkplotter.printc(self.StopButton.status(), box="_", dim=True)
if self.StopButton.status() == "STOP":
self.Finalize()
self.Continue = False
Finally, the results to plot are retrived from the vtk_output folder after each solve step by calling the FinalizeSolutionStep method. In this method a mesh object of vedo has been defined (stored in self.a), and to this vedo mesh object, the new displacements are added in order to visualize the deformed configuration.
def FinalizeSolutionStep(self):
super().FinalizeSolutionStep()
if self.timestep>1.5:
if self.timestep==2:
self.a = vtkplotter.load(f'./vtk_output/VISUALIZE_HROM_0_{self.timestep}.vtk')
displs = self.a.getPointArray("DISPLACEMENT")
if self.timestep>2:
b = vtkplotter.load(f'./vtk_output/VISUALIZE_HROM_0_{self.timestep}.vtk')
newpoints = b.points()
displs = b.getPointArray("DISPLACEMENT")
self.a.points(newpoints+displs)
self.a.pointColors(vtkplotter.mag(displs), cmap='jet').addScalarBar(vmin = 0, vmax = 0.009)
self.a.show(axes=1, viewup='z')
self.timestep +=1
Changing boundary conditions in real time
We can proceed to run the example with the usual command
python3 MainKratos.py
Then, the terminal will show the usual output of a Kratos simulation while a vedo window will appear showing the real-time solution. Grab and hold the slider to modify the load applied on the face of the Stanford Bunny. You will observe the corresponding deformation immediately.
Pressing the PAUSE button will interrupt the loop over this static simulation. After pressing PAUSE, the button will display CONTINUE. Press CONTINUE again to carry on with the simulation loop (You might need to press the spacebar after pressing CONTINUE).
Press the STOP button to call the Finalize method and finish the simulation.