Good afternoon,
I'm working towards coupling code_aster with a CFD flow code using the preCICE coupling library, with the objective of doing fluid structure interaction simulations (FSI).
The idea is to get forces from the flow solver and apply these to the FEM model to calculate the displacements. The displacements are then interpolated and communicated to the flow solver to calculate new forces, which then go to the FEM model, etc. etc.
So far I was able to do this using Python scripting of code_aster, with the "new" Pythonesque approach.
In pseudo-code:
m = read_mesh()
# the mesh contains HEXA_8 solid elements, and volume group 'all'
# and node-groups 'interface_$', with $ the index of the node in the
# interface the where the forces are read from CFD, and displacements are written to CFD.
model = code_aster.Model(mesh)
model.addModelingOnMesh(code_aster.Physics.Mechanics, code_aster.Modelings.Tridimensional)
model.build()
# E, NU and RHO are defined
materialProperties = code_aster.MaterialProperty('ELAS')
materialProperties.addPropertyReal('E', E, True)
materialProperties.addPropertyReal('NU', NU, True)
materialProperties.addPropertyReal('RHO', RHO, True)
material = code_aster.Material()
material.addMaterialProperty(materialProperties)
material.build()
materialField = code_aster.MaterialField(mesh)
materialField.addMaterialsOnGroupOfCells(material, ['all'])
materialField.buildWithoutExternalStateVariables()
while coupling.is_ongoing():
timestep = read_timestep() # from the coupling library
# read the forces that come from CFD. These have been
# interpolated to the nodes of the FEM interface.
forces = read_forces()
meca = code_aster.LinearStaticAnalysis(model, materialField)
for idx in range(len(interface_nodes)):
load = code_aster.ForceReal()
load.setValue(Fx, forces[idx, 0])
load.setValue(Fy, forces[idx, 1])
load.setValue(Fz, forces[idx, 2]) # 2D simulation
nodalForce = code_aster.NodalForceReal(model)
nodalForce.setValue(load, "interface_{0}".format(idx))
nodalForce.build()
meca.addLoad(nodalForce)
solver = code_aster.MumpsSolver()
meca.setLinearSolver(solver)
result = meca.execute()
displacementsField = result.getFieldOnNodesReal('DEPL', 1)
displacements = displacementsField.exportToSimpleFieldOnNodes()
displacements.updateValuePointers()
# communicate the displacements of the interface to the CFD code
write_displacements(interface, displacements)
# update the FEM mesh coordinates for the next coupling.
update_mesh_coordinates(m, displacements)
code_aster.close()
In principle this works, as the forces are received and applied, and the displacements are written and received by the CFD solver.
I have realized, however, that this method does not allow for the building up of stress/strain in the material from one coupling to the next, as each coupling starts with a deformed mesh that is stress/strain free. Any elastic/dynamic behavior is therefore not observed.
So (finally) my question is: how can I do this properly? Should I use STAT_NON_LINE? I have read in the documentation that it allows to set an initial state, or to reuse a previous calculation, or to use PILOTAGE, but I have not found many examples on how to do this.
Any hints are welcome :)