Skip to content

Commit

Permalink
Merge pull request #12568 from KratosMultiphysics/fsi/hotfix-embedded…
Browse files Browse the repository at this point in the history
…-solver-traction-sign

[Hotfix][FSI] Embedded solver traction sign
  • Loading branch information
rubenzorrilla authored Jul 23, 2024
2 parents 0128c9a + 09be4c0 commit 9c37e24
Show file tree
Hide file tree
Showing 10 changed files with 9,753 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,11 @@ def _MapFluidInterfaceTraction(self):

# Convert the pressure scalar load to a traction vector one
# This is required in the IBQN case as the structure and fluid interface residual sizes must match
# Note that we do not swap the traction sign as the normal considered is the positive interface outwards one
# As a difference to the standard body-fitted solver, which uses the fluid reaction that points to the fluid
# the positive interface outwards normal alredy points to the structure
if self._GetConvergenceAccelerator().IsBlockNewton():
swap_traction_sign = True
swap_traction_sign = False
self._GetPartitionedFSIUtilities().CalculateTractionFromPressureValues(
self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(),
KratosMultiphysics.POSITIVE_FACE_PRESSURE,
Expand Down Expand Up @@ -395,7 +398,10 @@ def _MapFluidInterfaceTraction(self):
0)

# Convert the pressure scalar load to a traction vector one
swap_traction_sign = True
# Note that we do not swap the traction sign as the normal considered is the positive interface outwards one
# As a difference to the standard body-fitted solver, which uses the fluid reaction that points to the fluid
# the positive interface outwards normal alredy points to the structure
swap_traction_sign = False
self._GetPartitionedFSIUtilities().CalculateTractionFromPressureValues(
self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(),
KratosMultiphysics.POSITIVE_FACE_PRESSURE,
Expand Down
159 changes: 159 additions & 0 deletions applications/FSIApplication/tests/embedded_fsi_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import os
import copy

import KratosMultiphysics
import KratosMultiphysics.KratosUnittest as KratosUnittest

from KratosMultiphysics.FSIApplication import fsi_analysis
from KratosMultiphysics.kratos_utilities import DeleteTimeFiles
from KratosMultiphysics.kratos_utilities import DeleteFilesEndingWith

class WorkFolderScope:
def __init__(self, work_folder):
self.currentPath = os.getcwd()
self.scope = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)),work_folder))

def __enter__(self):
os.chdir(self.scope)

def __exit__(self, type, value, traceback):
os.chdir(self.currentPath)

class EmbeddedFsiTest(KratosUnittest.TestCase):

def setUp(self):
self.print_output = False
self.reference_values_check = True
self.reference_values_output = False
self.check_relative_tolerance = 1.0e-6
self.check_absolute_tolerance = 1.0e-8
self.work_folder = "embedded_fsi_test"
self.settings = "ProjectParameters.json"

def tearDown(self):
DeleteTimeFiles(self.work_folder)
if not self.print_output:
DeleteFilesEndingWith(self.work_folder, ".post.bin")
DeleteFilesEndingWith(self.work_folder, ".post.lst")

def testEmbeddedVolumetricMVQN(self):
self.structure_filename = "embedded_fsi_test_structure_volumetric"
self.convergence_accelerator = "MVQN"
self.check_variables_list = ["DISPLACEMENT_X", "DISPLACEMENT_Y", "POSITIVE_FACE_PRESSURE"]

with WorkFolderScope(self.work_folder):
model = KratosMultiphysics.Model()
parameter_file = open(self.settings, 'r')
self.parameters = KratosMultiphysics.Parameters(parameter_file.read())
self._CustomizeProjectParameters()
fsi_analysis.FsiAnalysis(model, self.parameters).Run()

def testEmbeddedVolumetricIBQNMVQN(self):
self.structure_filename = "embedded_fsi_test_structure_volumetric"
self.convergence_accelerator = "IBQN_MVQN"
self.check_variables_list = ["DISPLACEMENT_X", "DISPLACEMENT_Y", "POSITIVE_FACE_PRESSURE"]

with WorkFolderScope(self.work_folder):
model = KratosMultiphysics.Model()
parameter_file = open(self.settings, 'r')
self.parameters = KratosMultiphysics.Parameters(parameter_file.read())
self._CustomizeProjectParameters()
fsi_analysis.FsiAnalysis(model, self.parameters).Run()

def _CustomizeProjectParameters(self):
self.parameters["solver_settings"]["structure_solver_settings"]["model_import_settings"]["input_filename"].SetString(self.structure_filename)
self.parameters["solver_settings"]["coupling_settings"]["coupling_strategy_settings"]["solver_type"].SetString(self.convergence_accelerator)

if self.print_output:
self._AddOutput()

if self.reference_values_output:
self._AddReferenceValuesOutput()

if self.reference_values_check:
self._AddReferenceValuesCheck()

def _AddOutput(self):
gid_output_settings = KratosMultiphysics.Parameters("""{
"python_module" : "gid_output_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "GiDOutputProcess",
"Parameters" : {
"model_part_name" : "TO_BE_DEFINED",
"output_name" : "TO_BE_DEFINED",
"postprocess_parameters" : {
"result_file_configuration" : {
"gidpost_flags" : {
"GiDPostMode" : "GiD_PostBinary",
"WriteDeformedMeshFlag" : "WriteDeformed",
"WriteConditionsFlag" : "WriteConditions",
"MultiFileFlag" : "SingleFile"
},
"file_label" : "time",
"output_control_type" : "step",
"output_interval" : 1,
"body_output" : true,
"node_output" : false,
"skin_output" : false,
"plane_output" : [],
"nodal_results" : [],
"gauss_point_results" : []
},
"point_data_configuration" : []
}
}
}""")

fluid_output_settings = copy.deepcopy(gid_output_settings)
fluid_output_settings["Parameters"]["model_part_name"].SetString("FluidModelPart")
fluid_output_settings["Parameters"]["output_name"].SetString(f"{self.structure_filename}_{self.convergence_accelerator}_fluid")
fluid_output_settings["Parameters"]["postprocess_parameters"]["result_file_configuration"]["nodal_results"].SetStringArray(["VELOCITY","PRESSURE"])
self.parameters["output_processes"]["gid_output"].Append(fluid_output_settings)

structure_output_settings = copy.deepcopy(gid_output_settings)
structure_output_settings["Parameters"]["model_part_name"].SetString("Structure")
structure_output_settings["Parameters"]["output_name"].SetString(f"{self.structure_filename}_{self.convergence_accelerator}_structure")
structure_output_settings["Parameters"]["postprocess_parameters"]["result_file_configuration"]["nodal_results"].SetStringArray(["DISPLACEMENT"])
self.parameters["output_processes"]["gid_output"].Append(structure_output_settings)

def _AddReferenceValuesOutput(self):
json_output_settings = KratosMultiphysics.Parameters("""{
"python_module" : "json_output_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "JsonOutputProcess",
"Parameters" : {
"output_variables" : [],
"output_file_name" : "TO_BE_DEFINED",
"model_part_name" : "Structure",
"time_frequency" : 0.01
}
}""")
output_file_name = f"{self.structure_filename}_{self.convergence_accelerator}_results.json"
json_output_settings["Parameters"]["output_file_name"].SetString(output_file_name)
json_output_settings["Parameters"]["output_variables"].SetStringArray(self.check_variables_list)
self.parameters["processes"]["json_check_process_list"].Append(json_output_settings)

def _AddReferenceValuesCheck(self):
json_check_settings = KratosMultiphysics.Parameters("""{
"python_module" : "from_json_check_result_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "FromJsonCheckResultProcess",
"Parameters" : {
"check_variables" : [],
"input_file_name" : "TO_BE_DEFINED",
"model_part_name" : "Structure",
"tolerance" : 0.0,
"relative_tolerance" : 0.0,
"time_frequency" : 0.01
}
}""")
input_file_name = f"{self.structure_filename}_{self.convergence_accelerator}_results.json"
json_check_settings["Parameters"]["input_file_name"].SetString(input_file_name)
json_check_settings["Parameters"]["check_variables"].SetStringArray(self.check_variables_list)
json_check_settings["Parameters"]["tolerance"].SetDouble(self.check_absolute_tolerance)
json_check_settings["Parameters"]["relative_tolerance"].SetDouble(self.check_relative_tolerance)
self.parameters["processes"]["json_check_process_list"].Append(json_check_settings)

if __name__ == '__main__':
KratosUnittest.main()

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"properties" : [{
"model_part_name" : "FluidModelPart",
"properties_id" : 0,
"Material" : null
},{
"model_part_name" : "FluidModelPart.FluidParts_Fluid",
"properties_id" : 1,
"Material" : {
"constitutive_law" : {
"name" : "Newtonian2DLaw"
},
"Variables" : {
"DENSITY" : 1.0e3,
"DYNAMIC_VISCOSITY" : 1.0e-3
},
"Tables" : null
}
}]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
{
"analysis_stage" : "KratosMultiphysics.FSIApplication.fsi_analysis",
"problem_data": {
"problem_name": "embedded_fsi_test",
"parallel_type": "OpenMP",
"echo_level": 0,
"start_time": 0.0,
"end_time": 9.99e-1
},
"solver_settings": {
"solver_type": "partitioned_embedded",
"coupling_scheme": "dirichlet_neumann",
"echo_level": 1,
"structure_solver_settings": {
"solver_type" : "Dynamic",
"model_part_name" : "Structure",
"domain_size" : 2,
"echo_level" : 0,
"analysis_type" : "non_linear",
"time_integration_method" : "implicit",
"scheme_type" : "bossak",
"model_import_settings" : {
"input_type": "mdpa",
"input_filename": "TO_BE_SET"
},
"material_import_settings": {
"materials_filename": "StructuralMaterialsVolumetric.json"
},
"time_stepping": {
"time_step": 1.0e-1
},
"line_search" : false,
"convergence_criterion" : "residual_criterion",
"displacement_relative_tolerance" : 1e-5,
"displacement_absolute_tolerance" : 1e-7,
"residual_relative_tolerance" : 1e-5,
"residual_absolute_tolerance" : 1e-7,
"max_iteration" : 20
},
"fluid_solver_settings":{
"model_part_name" : "FluidModelPart",
"domain_size" : 2,
"solver_type" : "Embedded",
"model_import_settings" : {
"input_type" : "mdpa",
"input_filename" : "embedded_fsi_test_fluid"
},
"material_import_settings": {
"materials_filename": "FluidMaterials.json"
},
"distance_modification_settings": {
"distance_threshold": 1.0e-3
},
"echo_level" : 0,
"compute_reactions" : true,
"maximum_iterations" : 10,
"relative_velocity_tolerance" : 1e-5,
"absolute_velocity_tolerance" : 1e-7,
"relative_pressure_tolerance" : 1e-5,
"absolute_pressure_tolerance" : 1e-7,
"assign_neighbour_elements_to_conditions" : true,
"volume_model_part_name" : "FluidModelPart.FluidParts_Fluid",
"skin_parts" : ["FluidModelPart.NoSlip2D_Walls"],
"no_skin_parts" : [],
"time_stepping" : {
"automatic_time_step": false,
"time_step": 1.0e-1
},
"formulation": {
"element_type": "embedded_weakly_compressible_navier_stokes",
"is_slip": true,
"slip_length": 1.0e6,
"penalty_coefficient": 1.0e3,
"dynamic_tau": 1.0
},
"fm_ale_settings": {
"fm_ale_step_frequency": 1,
"mesh_movement": "implicit",
"fm_ale_solver_settings": {
"structure_model_part_name": "FSICouplingInterfaceFluid",
"virtual_model_part_name": "VirtualModelPart",
"linear_solver_settings": {
"preconditioner_type": "amg",
"solver_type": "amgcl",
"smoother_type": "ilu0",
"krylov_type": "cg",
"max_iteration": 2000,
"verbosity": 0,
"tolerance": 1e-8,
"scaling": false,
"use_block_matrices_if_possible": true
},
"embedded_nodal_variable_settings": {
"gradient_penalty_coefficient": 5.0e-2,
"linear_solver_settings": {
"preconditioner_type": "amg",
"solver_type": "amgcl",
"smoother_type": "ilu0",
"krylov_type": "cg",
"max_iteration": 2000,
"verbosity": 0,
"tolerance": 1e-8,
"scaling": false,
"block_size": 1,
"use_block_matrices_if_possible": true
}
}
}
}
},
"coupling_settings":{
"nl_tol": 1e-4,
"nl_max_it": 10,
"coupling_strategy_settings": {
"solver_type": "MVQN"
},
"structure_interfaces_list": ["Structure.FluidInterface"]
}
},
"processes":{
"structure_constraints_process_list" : [{
"python_module" : "assign_vector_variable_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "AssignVectorVariableProcess",
"Parameters" : {
"model_part_name" : "Structure.LeftEdge",
"variable_name" : "DISPLACEMENT",
"interval" : [0.0,"End"],
"constrained" : [true,true,false],
"value" : [0.0,0.0,null]
}
}],
"structure_loads_process_list" : [],
"fluid_initial_conditions_process_list" : [],
"fluid_boundary_conditions_process_list" : [{
"python_module" : "apply_noslip_process",
"kratos_module" : "KratosMultiphysics.FluidDynamicsApplication",
"process_name" : "ApplyNoSlipProcess",
"Parameters" : {
"model_part_name" : "FluidModelPart.NoSlip2D_Walls"
}
},{
"python_module" : "assign_scalar_variable_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "AssignScalarVariableProcess",
"Parameters" : {
"model_part_name" : "FluidModelPart.PressureConstraints2D_TopRightCorner",
"variable_name" : "PRESSURE",
"interval" : [0.0,"End"],
"constrained" : true,
"value" : 0.0
}
},{
"python_module" : "assign_vector_variable_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "AssignVectorVariableProcess",
"Parameters" : {
"model_part_name" : "FluidModelPart.NoSlip2D_Walls",
"variable_name" : "MESH_DISPLACEMENT",
"interval" : [0.0,"End"],
"constrained" : [true,true,false],
"value" : [0.0,0.0,null]
}
}],
"fluid_gravity" : [{
"python_module" : "assign_vector_by_direction_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "AssignVectorByDirectionProcess",
"Parameters" : {
"model_part_name" : "FluidModelPart.FluidParts_Fluid",
"variable_name" : "BODY_FORCE",
"modulus" : 10,
"constrained" : false,
"direction" : [0.0,-1.0,0.0]
}
}],
"fluid_auxiliar_process_list" : [{
"python_module": "apply_embedded_postprocess_process",
"kratos_module": "KratosMultiphysics.FluidDynamicsApplication",
"process_name": "ApplyEmbeddedPostprocessrocess",
"Parameters": {
"model_part_name": "FluidModelPart.FluidParts_Fluid"
}
}],
"json_check_process_list" : []
},
"output_processes":{
"gid_output" : []
}
}
Loading

0 comments on commit 9c37e24

Please sign in to comment.