Skip to content

Commit 0fcf5bb

Browse files
authored
Allow FSI+CHT (aerothermoelasticity) (#2807)
* allow fsi+cht * Apply suggestions from code review Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> * set regression values * back to develop
1 parent 4517692 commit 0fcf5bb

14 files changed

Lines changed: 264 additions & 295 deletions

File tree

Common/src/CConfig.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,9 +1311,9 @@ void CConfig::SetConfig_Options() {
13111311
/* DESCRIPTION: Definition of the turbulent thermal conductivity model (CONSTANT_PRANDTL_TURB (default), NONE). */
13121312
addEnumOption("TURBULENT_CONDUCTIVITY_MODEL", Kind_ConductivityModel_Turb, TurbConductivityModel_Map, CONDUCTIVITYMODEL_TURB::CONSTANT_PRANDTL);
13131313

1314-
/*--- Options related to Constant Thermal Conductivity Model ---*/
1314+
/*--- Options related to Constant Thermal Conductivity Model ---*/
13151315

1316-
/* DESCRIPTION: default value for AIR */
1316+
/* DESCRIPTION: default value for AIR */
13171317
addDoubleListOption("THERMAL_CONDUCTIVITY_CONSTANT", nThermal_Conductivity_Constant , Thermal_Conductivity_Constant);
13181318

13191319
/*--- Options related to temperature polynomial coefficients for fluid models. ---*/

SU2_CFD/include/interfaces/CInterface.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#pragma once
3030

3131
#include "../../../Common/include/parallelization/mpi_structure.hpp"
32+
#include "../../../Common/include/option_structure.hpp"
3233

3334
#include <cmath>
3435
#include <string>
@@ -77,7 +78,7 @@ class CInterface {
7778
/*!
7879
* \brief Constructor of the class.
7980
*/
80-
CInterface(void);
81+
CInterface();
8182

8283
/*!
8384
* \overload
@@ -89,7 +90,7 @@ class CInterface {
8990
/*!
9091
* \brief Destructor of the class.
9192
*/
92-
virtual ~CInterface(void);
93+
virtual ~CInterface();
9394

9495
/*!
9596
* \brief Interpolate data and broadcast it into all processors, for nonmatching meshes.
@@ -224,4 +225,11 @@ class CInterface {
224225
* \param[in] val_contact_resistance - Contact resistance value in m^2/W
225226
*/
226227
inline virtual void SetContactResistance(su2double val_contact_resistance) {};
228+
229+
/*!
230+
* \brief These can be used to chain interfaces between the same zones but for other variables,
231+
* without having to mix physics in the interface classes. Currently this is used for FSI+CHT.
232+
*/
233+
ENUM_TRANSFER NextInterfaceType = ENUM_TRANSFER::NO_TRANSFER;
234+
CInterface* NextInterface = nullptr;
227235
};

SU2_CFD/src/drivers/CDriver.cpp

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,6 +2443,31 @@ void CDriver::InitializeInterface(CConfig **config, CSolver***** solver, CGeomet
24432443
interpolation[donor][target] = unique_ptr<CInterpolator>(CInterpolatorFactory::CreateInterpolator(
24442444
geometry, config, interpolation[target][donor].get(), donor, target));
24452445

2446+
/*--- Helpers with logic to create CHT interfaces. ---*/
2447+
2448+
auto GetChtInterfaceType = [donor, target, config](bool heat_donor, bool heat_target) {
2449+
if (heat_donor && heat_target) return CONJUGATE_HEAT_SS;
2450+
2451+
const auto fluidZone = heat_target ? donor : target;
2452+
if (config[fluidZone]->GetEnergy_Equation() ||
2453+
config[fluidZone]->GetKind_Regime() == ENUM_REGIME::COMPRESSIBLE ||
2454+
config[fluidZone]->GetKind_FluidModel() == ENUM_FLUIDMODEL::FLUID_FLAMELET) {
2455+
return heat_target ? CONJUGATE_HEAT_FS : CONJUGATE_HEAT_SF;
2456+
} else if (config[fluidZone]->GetWeakly_Coupled_Heat()) {
2457+
return heat_target ? CONJUGATE_HEAT_WEAKLY_FS : CONJUGATE_HEAT_WEAKLY_SF;
2458+
}
2459+
return NO_TRANSFER;
2460+
};
2461+
2462+
auto MakeChtInterface = [&](const auto type) {
2463+
if (type != NO_TRANSFER) {
2464+
if (rank == MASTER_NODE) cout << " Conjugate heat variables." << endl;
2465+
return new CConjugateHeatInterface(4, 0);
2466+
}
2467+
if (rank == MASTER_NODE) cout << " NO heat variables." << endl;
2468+
return static_cast<CConjugateHeatInterface*>(nullptr);
2469+
};
2470+
24462471
/*--- The type of variables transferred depends on the donor/target physics. ---*/
24472472

24482473
const bool heat_target = config[target]->GetHeatProblem();
@@ -2467,16 +2492,26 @@ void CDriver::InitializeInterface(CConfig **config, CSolver***** solver, CGeomet
24672492
interface[donor][target] = new CDiscAdjFlowTractionInterface(nDim, nConst, config[donor], conservative);
24682493
}
24692494
if (rank == MASTER_NODE) cout << "fluid " << (conservative? "forces." : "tractions.") << endl;
2495+
2496+
if (config[target]->GetWeakly_Coupled_Heat()) {
2497+
interface[donor][target]->NextInterfaceType = GetChtInterfaceType(false, true);
2498+
interface[donor][target]->NextInterface = MakeChtInterface(interface[donor][target]->NextInterfaceType);
2499+
}
24702500
}
24712501
else if (structural_donor && (fluid_target || heat_target)) {
24722502
if (solver_container[target][INST_0][MESH_0][MESH_SOL] == nullptr) {
24732503
SU2_MPI::Error("Mesh deformation was not correctly specified for the fluid/heat zone.\n"
24742504
"Use DEFORM_MESH=YES, and setup MARKER_DEFORM_MESH=(...)", CURRENT_FUNCTION);
24752505
}
24762506
interface_type = BOUNDARY_DISPLACEMENTS;
2477-
if (!config[donor]->GetTime_Domain()) interface[donor][target] = new CDisplacementsInterface(nDim, 0);
2478-
else interface[donor][target] = new CDisplacementsInterface(2*nDim, 0);
2507+
const auto nVar = config[donor]->GetTime_Domain() ? 2 * nDim : nDim;
2508+
interface[donor][target] = new CDisplacementsInterface(nVar, 0);
24792509
if (rank == MASTER_NODE) cout << "boundary displacements from the structural solver." << endl;
2510+
2511+
if (fluid_target && config[donor]->GetWeakly_Coupled_Heat()) {
2512+
interface[donor][target]->NextInterfaceType = GetChtInterfaceType(true, false);
2513+
interface[donor][target]->NextInterface = MakeChtInterface(interface[donor][target]->NextInterfaceType);
2514+
}
24802515
}
24812516
else if (fluid_donor && fluid_target) {
24822517
/*--- Interface handling for turbomachinery applications. ---*/
@@ -2487,48 +2522,27 @@ void CDriver::InitializeInterface(CConfig **config, CSolver***** solver, CGeomet
24872522
interface_type = MIXING_PLANE;
24882523
auto nVar = solver[donor][INST_0][MESH_0][FLOW_SOL]->GetnVar();
24892524
interface[donor][target] = new CMixingPlaneInterface(nVar, 0);
2490-
if (rank == MASTER_NODE) cout << "using a mixing-plane interface from donor zone " << donor << " to target zone " << target << "." << endl;
2525+
if (rank == MASTER_NODE) cout << " Using a mixing-plane interface from donor zone " << donor << " to target zone " << target << "." << endl;
24912526
break;
24922527
}
24932528
case TURBO_INTERFACE_KIND::FROZEN_ROTOR: {
24942529
auto nVar = solver[donor][INST_0][MESH_0][FLOW_SOL]->GetnPrimVar();
24952530
interface_type = SLIDING_INTERFACE;
24962531
interface[donor][target] = new CSlidingInterface(nVar, 0);
2497-
if (rank == MASTER_NODE) cout << "using a fluid interface interface from donor zone " << donor << " to target zone " << target << "." << endl;
2532+
if (rank == MASTER_NODE) cout << " Using a fluid interface interface from donor zone " << donor << " to target zone " << target << "." << endl;
24982533
}
24992534
}
25002535
}
25012536
else{
25022537
auto nVar = solver[donor][INST_0][MESH_0][FLOW_SOL]->GetnPrimVar();
25032538
interface_type = SLIDING_INTERFACE;
25042539
interface[donor][target] = new CSlidingInterface(nVar, 0);
2505-
if (rank == MASTER_NODE) cout << "sliding interface." << endl;
2540+
if (rank == MASTER_NODE) cout << " Sliding interface." << endl;
25062541
}
25072542
}
25082543
else if (heat_donor || heat_target) {
2509-
if (heat_donor && heat_target){
2510-
interface_type = CONJUGATE_HEAT_SS;
2511-
2512-
} else {
2513-
2514-
const auto fluidZone = heat_target? donor : target;
2515-
if (config[fluidZone]->GetEnergy_Equation() || (config[fluidZone]->GetKind_Regime() == ENUM_REGIME::COMPRESSIBLE)
2516-
|| (config[fluidZone]->GetKind_FluidModel() == ENUM_FLUIDMODEL::FLUID_FLAMELET))
2517-
interface_type = heat_target? CONJUGATE_HEAT_FS : CONJUGATE_HEAT_SF;
2518-
else if (config[fluidZone]->GetWeakly_Coupled_Heat())
2519-
interface_type = heat_target? CONJUGATE_HEAT_WEAKLY_FS : CONJUGATE_HEAT_WEAKLY_SF;
2520-
else
2521-
interface_type = NO_TRANSFER;
2522-
}
2523-
2524-
if (interface_type != NO_TRANSFER) {
2525-
auto nVar = 4;
2526-
interface[donor][target] = new CConjugateHeatInterface(nVar, 0);
2527-
if (rank == MASTER_NODE) cout << "conjugate heat variables." << endl;
2528-
}
2529-
else {
2530-
if (rank == MASTER_NODE) cout << "NO heat variables." << endl;
2531-
}
2544+
interface_type = GetChtInterfaceType(heat_donor, heat_target);
2545+
interface[donor][target] = MakeChtInterface(interface_type);
25322546
}
25332547
else {
25342548
if (solver[donor][INST_0][MESH_0][FLOW_SOL] == nullptr)
@@ -2537,7 +2551,7 @@ void CDriver::InitializeInterface(CConfig **config, CSolver***** solver, CGeomet
25372551
auto nVar = solver[donor][INST_0][MESH_0][FLOW_SOL]->GetnVar();
25382552
interface_type = CONSERVATIVE_VARIABLES;
25392553
interface[donor][target] = new CConservativeVarsInterface(nVar, 0);
2540-
if (rank == MASTER_NODE) cout << "generic conservative variables." << endl;
2554+
if (rank == MASTER_NODE) cout << " Generic conservative variables." << endl;
25412555
}
25422556
}
25432557

SU2_CFD/src/drivers/CMultizoneDriver.cpp

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -549,19 +549,19 @@ bool CMultizoneDriver::TransferData(unsigned short donorZone, unsigned short tar
549549

550550
/*--- Select the transfer method according to the magnitudes being transferred ---*/
551551

552-
auto BroadcastData = [&](int donorSol, int targetSol) {
553-
interface_container[donorZone][targetZone]->BroadcastData(
554-
*interpolator_container[donorZone][targetZone].get(),
555-
solver_container[donorZone][INST_0][MESH_0][donorSol],
556-
solver_container[targetZone][INST_0][MESH_0][targetSol],
557-
geometry_container[donorZone][INST_0][MESH_0],
558-
geometry_container[targetZone][INST_0][MESH_0],
559-
config_container[donorZone],
560-
config_container[targetZone]);
561-
};
562-
563-
switch (interface_types[donorZone][targetZone]) {
564-
552+
auto HandleInterfaceType = [&] (const auto interface_type, auto* interface) {
553+
auto BroadcastData = [&](int donorSol, int targetSol) {
554+
interface->BroadcastData(
555+
*interpolator_container[donorZone][targetZone],
556+
solver_container[donorZone][INST_0][MESH_0][donorSol],
557+
solver_container[targetZone][INST_0][MESH_0][targetSol],
558+
geometry_container[donorZone][INST_0][MESH_0],
559+
geometry_container[targetZone][INST_0][MESH_0],
560+
config_container[donorZone],
561+
config_container[targetZone]);
562+
};
563+
564+
switch (interface_type) {
565565
case SLIDING_INTERFACE:
566566
BroadcastData(FLOW_SOL, FLOW_SOL);
567567

@@ -598,35 +598,49 @@ bool CMultizoneDriver::TransferData(unsigned short donorZone, unsigned short tar
598598
case FLOW_TRACTION:
599599
BroadcastData(FLOW_SOL, FEA_SOL);
600600
break;
601-
case MIXING_PLANE:
602-
{
601+
case MIXING_PLANE: {
603602
const auto nMarkerInt = config_container[donorZone]->GetnMarker_MixingPlaneInterface() / 2;
604603

605-
/*--- Transfer the average value from the donorZone to the targetZone ---*/
606-
/*--- Loops over the mixing planes defined in the config file to find the correct mixing plane for the donor-target combination ---*/
604+
/*--- Transfer the average value from the donorZone to the targetZone
605+
* Loops over the mixing planes defined in the config file to find the
606+
* correct mixing plane for the donor-target combination ---*/
607607
for (auto iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
608-
interface_container[donorZone][targetZone]->AllgatherAverage(solver_container[donorZone][INST_0][MESH_0][FLOW_SOL],solver_container[targetZone][INST_0][MESH_0][FLOW_SOL],
609-
geometry_container[donorZone][INST_0][MESH_0],geometry_container[targetZone][INST_0][MESH_0],
610-
config_container[donorZone], config_container[targetZone], iMarkerInt );
608+
interface->AllgatherAverage(
609+
solver_container[donorZone][INST_0][MESH_0][FLOW_SOL],
610+
solver_container[targetZone][INST_0][MESH_0][FLOW_SOL],
611+
geometry_container[donorZone][INST_0][MESH_0],
612+
geometry_container[targetZone][INST_0][MESH_0],
613+
config_container[donorZone], config_container[targetZone], iMarkerInt);
611614
}
612615

613616
/*--- Set average value donorZone->targetZone ---*/
614-
interface_container[donorZone][targetZone]->SetAverageValues(solver_container[donorZone][INST_0][MESH_0][FLOW_SOL],solver_container[targetZone][INST_0][MESH_0][FLOW_SOL], donorZone);
617+
interface->SetAverageValues(solver_container[donorZone][INST_0][MESH_0][FLOW_SOL],
618+
solver_container[targetZone][INST_0][MESH_0][FLOW_SOL], donorZone);
615619

616620
/*--- Set average geometrical properties FROM donorZone IN targetZone ---*/
617-
geometry_container[targetZone][INST_0][MESH_0]->SetAvgTurboGeoValues(config_container[iZone],geometry_container[iZone][INST_0][MESH_0], iZone);
618-
619-
break;
620-
}
621+
geometry_container[targetZone][INST_0][MESH_0]->SetAvgTurboGeoValues(
622+
config_container[iZone], geometry_container[iZone][INST_0][MESH_0], iZone);
623+
} break;
621624
case NO_TRANSFER:
622625
case ZONES_ARE_EQUAL:
623626
case NO_COMMON_INTERFACE:
624627
break;
625628
default:
626-
if(rank == MASTER_NODE)
629+
if (rank == MASTER_NODE) {
627630
cout << "WARNING: One of the intended interface transfer routines is not "
628631
<< "known to the chosen driver and has not been executed." << endl;
632+
}
629633
break;
634+
}
635+
};
636+
637+
auto type = interface_types[donorZone][targetZone];
638+
auto* interface = interface_container[donorZone][targetZone];
639+
640+
while (interface != nullptr) {
641+
HandleInterfaceType(type, interface);
642+
type = interface->NextInterfaceType;
643+
interface = interface->NextInterface;
630644
}
631645

632646
return UpdateMesh;

SU2_CFD/src/interfaces/CInterface.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ CInterface::~CInterface() {
5757

5858
delete[] SpanValueCoeffTarget;
5959
delete[] SpanLevelDonor;
60+
61+
delete NextInterface;
6062
}
6163

6264
void CInterface::BroadcastData(const CInterpolator& interpolator,

SU2_CFD/src/interfaces/fsi/CFlowTractionInterface.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ void CFlowTractionInterface::GetPhysical_Constants(CSolver *flow_solution, CSolv
158158
Physical_Constants[1] = ModAmpl;
159159

160160
/*--- For static FSI, we cannot apply the ramp like this ---*/
161-
if ((!flow_config->GetTime_Domain())){
161+
if (!flow_config->GetTime_Domain()) {
162162
Physical_Constants[1] = 1.0;
163-
if (Ramp_Load){
163+
if (Ramp_Load) {
164164
CurrentTime = static_cast<su2double>(struct_config->GetOuterIter());
165165
Ramp_Time = static_cast<su2double>(struct_config->GetnIterFSI_Ramp() - 1);
166166

SU2_CFD/src/solvers/CHeatSolver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ void CHeatSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *
257257
solver[MESH_0][HEAT_SOL]->InitiateComms(geometry[MESH_0], config, MPI_QUANTITIES::SOLUTION);
258258
solver[MESH_0][HEAT_SOL]->CompleteComms(geometry[MESH_0], config, MPI_QUANTITIES::SOLUTION);
259259

260+
SU2_OMP_SAFE_GLOBAL_ACCESS(config->SetGlobalParam(MAIN_SOLVER::HEAT_EQUATION, RUNTIME_HEAT_SYS);)
260261
solver[MESH_0][HEAT_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_HEAT_SYS, false);
261262

262263
/*--- Interpolate the solution down to the coarse multigrid levels ---*/

TestCases/fea_fsi/stat_fsi/config.cfg

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2-
% %
32
% SU2 configuration file %
4-
% Case description: Fluid structure interaction - Beam in channel - 2D - FEM %
5-
% Author: R.Sanchez %
6-
% Institution: Imperial College London %
7-
% %
3+
% Case description: Aero-thermo-elasticity %
84
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95

6+
% FSI settings
107
SOLVER= MULTIPHYSICS
8+
MULTIZONE_SOLVER= BLOCK_GAUSS_SEIDEL
9+
RAMP_LOADING= YES
10+
RAMP_FSI_ITER= 5
11+
BGS_RELAXATION= FIXED_PARAMETER
12+
STAT_RELAX_PARAMETER= 0.9
1113

12-
CONFIG_LIST = (configFlow.cfg, configFEA.cfg)
14+
CONFIG_LIST= ( configFlow.cfg, configFEA.cfg )
1315

14-
MULTIZONE_SOLVER = BLOCK_GAUSS_SEIDEL
16+
MARKER_ZONE_INTERFACE= ( wallF, wallS )
1517

16-
MARKER_ZONE_INTERFACE = (wallF, wallS)
18+
SCREEN_OUTPUT= \
19+
OUTER_ITER, INNER_ITER[0], AVG_BGS_RES[0], AVG_BGS_RES[1],\
20+
RMS_DENSITY[0], RMS_UTOL[1], RMS_TEMPERATURE[1], VMS[1],\
21+
TOTAL_HEATFLUX[1], DEFORM_MIN_VOLUME[0], DEFORM_ITER[0]
1722

18-
MULTIZONE_MESH = NO
19-
SCREEN_OUTPUT=(OUTER_ITER, BGS_DENSITY[0], AVG_BGS_RES[1], DEFORM_MIN_VOLUME[0], DEFORM_ITER[0])
2023
RESTART_SOL= NO
21-
RESTART_ITER = 0
24+
RESTART_ITER= 0
25+
26+
OUTER_ITER= 30
27+
CONV_RESIDUAL_MINVAL= -5
28+
29+
MULTIZONE_MESH= NO
30+
WRT_ZONE_CONV= NO
31+
OUTPUT_WRT_FREQ= 100
2232

23-
TIME_DOMAIN = NO
24-
OUTER_ITER = 8

0 commit comments

Comments
 (0)