Skip to content

Commit f2b75c5

Browse files
authored
Merge pull request #2017 from su2code/py_wrapper_heat_example
Python wrapper heat solver example + disc adj minor fixes and cleanup
2 parents 638cf83 + da66ed3 commit f2b75c5

11 files changed

Lines changed: 520 additions & 317 deletions

File tree

SU2_CFD/include/drivers/CDriverBase.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,25 @@ class CDriverBase {
473473
"MarkerSolutionTimeN of " + solver->GetSolverName(), false);
474474
}
475475

476+
/*!
477+
* \brief Get a read/write view of the solution at time N-1 on all mesh nodes of a solver.
478+
*/
479+
inline CPyWrapperMatrixView SolutionTimeN1(unsigned short iSolver) {
480+
auto* solver = GetSolverAndCheckMarker(iSolver);
481+
return CPyWrapperMatrixView(
482+
solver->GetNodes()->GetSolution_time_n1(), "SolutionTimeN1 of " + solver->GetSolverName(), false);
483+
}
484+
485+
/*!
486+
* \brief Get a read/write view of the solution at time N-1 on the mesh nodes of a marker.
487+
*/
488+
inline CPyWrapperMarkerMatrixView MarkerSolutionTimeN1(unsigned short iSolver, unsigned short iMarker) {
489+
auto* solver = GetSolverAndCheckMarker(iSolver, iMarker);
490+
return CPyWrapperMarkerMatrixView(
491+
solver->GetNodes()->GetSolution_time_n1(), main_geometry->vertex[iMarker], main_geometry->GetnVertex(iMarker),
492+
"MarkerSolutionTimeN1 of " + solver->GetSolverName(), false);
493+
}
494+
476495
/*!
477496
* \brief Get the flow solver primitive variable names with their associated indices.
478497
* These correspond to the column indices in the matrix returned by Primitives.

SU2_CFD/include/variables/CVariable.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ class CVariable {
500500
* \return Pointer to the solution (at time n-1) vector.
501501
*/
502502
inline su2double *GetSolution_time_n1(unsigned long iPoint) { return Solution_time_n1[iPoint]; }
503+
inline MatrixType& GetSolution_time_n1() { return Solution_time_n1; }
503504

504505
/*!
505506
* \brief Set the value of the old residual.

SU2_CFD/src/drivers/CDiscAdjSinglezoneDriver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ CDiscAdjSinglezoneDriver::~CDiscAdjSinglezoneDriver() {
129129

130130
void CDiscAdjSinglezoneDriver::Preprocess(unsigned long TimeIter) {
131131

132+
/*--- Set the current time iteration in the config and also in the driver
133+
* because the python interface doesn't offer an explicit way of doing it. ---*/
134+
135+
this->TimeIter = TimeIter;
132136
config_container[ZONE_0]->SetTimeIter(TimeIter);
133137

134138
/*--- Preprocess the adjoint iteration ---*/

SU2_CFD/src/drivers/CSinglezoneDriver.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,10 @@ void CSinglezoneDriver::StartSolver() {
110110

111111
void CSinglezoneDriver::Preprocess(unsigned long TimeIter) {
112112

113-
/*--- Set the current time iteration in the config ---*/
113+
/*--- Set the current time iteration in the config and also in the driver
114+
* because the python interface doesn't offer an explicit way of doing it. ---*/
114115

116+
this->TimeIter = TimeIter;
115117
config_container[ZONE_0]->SetTimeIter(TimeIter);
116118

117119
/*--- Store the current physical time in the config container, as

SU2_CFD/src/iteration/CDiscAdjFluidIteration.cpp

Lines changed: 167 additions & 251 deletions
Large diffs are not rendered by default.

SU2_CFD/src/iteration/CDiscAdjHeatIteration.cpp

Lines changed: 42 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -43,79 +43,64 @@ void CDiscAdjHeatIteration::Preprocess(COutput* output, CIntegration**** integra
4343
/*--- For the unsteady adjoint, load direct solutions from restart files. ---*/
4444

4545
if (config[val_iZone]->GetTime_Marching() != TIME_MARCHING::STEADY) {
46-
const int Direct_Iter = static_cast<int>(config[val_iZone]->GetUnst_AdjointIter()) - static_cast<int>(TimeIter) - 2 + dual_time;
46+
const int Direct_Iter = static_cast<int>(config[val_iZone]->GetUnst_AdjointIter()) -
47+
static_cast<int>(TimeIter) - 2 + dual_time;
4748

48-
/*--- For dual-time stepping we want to load the already converged solution at timestep n ---*/
49+
/*--- For dual-time stepping we want to load the already converged solution at previous timesteps.
50+
* In general we only load one file and shift the previously loaded solutions, on the first we
51+
* load one or two more (depending on dual time order). ---*/
4952

50-
if (TimeIter == 0) {
51-
if (dual_time_2nd) {
52-
/*--- Load solution at timestep n-2 ---*/
53-
54-
LoadUnsteady_Solution(geometry, solver, config, val_iZone, val_iInst, Direct_Iter - 2);
55-
56-
/*--- Push solution back to correct array ---*/
53+
if (dual_time_2nd) {
54+
LoadUnsteady_Solution(geometry, solver, config, val_iZone, val_iInst, Direct_Iter - 2);
55+
} else if (dual_time_1st) {
56+
LoadUnsteady_Solution(geometry, solver, config, val_iZone, val_iInst, Direct_Iter - 1);
57+
}
5758

59+
if (TimeIter == 0) {
60+
/*--- Push solution back one level. ---*/
61+
if (dual_time) {
5862
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
5963
solvers[iMesh][HEAT_SOL]->GetNodes()->Set_Solution_time_n();
60-
solvers[iMesh][HEAT_SOL]->GetNodes()->Set_Solution_time_n1();
6164
}
6265
}
63-
if (dual_time) {
64-
/*--- Load solution at timestep n-1 ---*/
6566

67+
/*--- If required load another time step. Push the previous time step to n-1 and the
68+
loaded time step to n. ---*/
69+
if (dual_time_2nd) {
6670
LoadUnsteady_Solution(geometry, solver, config, val_iZone, val_iInst, Direct_Iter - 1);
6771

68-
/*--- Push solution back to correct array ---*/
69-
7072
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
73+
solvers[iMesh][HEAT_SOL]->GetNodes()->Set_Solution_time_n1();
7174
solvers[iMesh][HEAT_SOL]->GetNodes()->Set_Solution_time_n();
7275
}
7376
}
7477

75-
/*--- Load solution timestep n ---*/
76-
78+
/*--- Load current solution. ---*/
7779
LoadUnsteady_Solution(geometry, solver, config, val_iZone, val_iInst, Direct_Iter);
7880
}
7981
if ((TimeIter > 0) && dual_time) {
80-
/*--- Load solution timestep n - 2 ---*/
81-
82-
LoadUnsteady_Solution(geometry, solver, config, val_iZone, val_iInst, Direct_Iter - 2);
83-
8482
/*--- Temporarily store the loaded solution in the Solution_Old array ---*/
85-
8683
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++)
8784
solvers[iMesh][HEAT_SOL]->Set_OldSolution();
8885

89-
/*--- Set Solution at timestep n to solution at n-1 ---*/
90-
86+
/*--- Move timestep n to current solution. ---*/
9187
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
9288
for (auto iPoint = 0ul; iPoint < geometry[val_iZone][val_iInst][iMesh]->GetnPoint(); iPoint++) {
9389
solvers[iMesh][HEAT_SOL]->GetNodes()->SetSolution(
9490
iPoint, solvers[iMesh][HEAT_SOL]->GetNodes()->GetSolution_time_n(iPoint));
9591
}
9692
}
97-
if (dual_time_1st) {
98-
/*--- Set Solution at timestep n-1 to the previously loaded solution ---*/
99-
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
100-
for (auto iPoint = 0ul; iPoint < geometry[val_iZone][val_iInst][iMesh]->GetnPoint(); iPoint++) {
101-
solvers[iMesh][HEAT_SOL]->GetNodes()->Set_Solution_time_n(
102-
iPoint, solvers[iMesh][HEAT_SOL]->GetNodes()->GetSolution_time_n1(iPoint));
103-
}
104-
}
105-
}
106-
if (dual_time_2nd) {
107-
/*--- Set Solution at timestep n-1 to solution at n-2 ---*/
108-
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
109-
for (auto iPoint = 0ul; iPoint < geometry[val_iZone][val_iInst][iMesh]->GetnPoint(); iPoint++) {
110-
solvers[iMesh][HEAT_SOL]->GetNodes()->Set_Solution_time_n(
111-
iPoint, solvers[iMesh][HEAT_SOL]->GetNodes()->GetSolution_time_n1(iPoint));
112-
}
113-
}
114-
/*--- Set Solution at timestep n-2 to the previously loaded solution ---*/
115-
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
116-
for (auto iPoint = 0ul; iPoint < geometry[val_iZone][val_iInst][iMesh]->GetnPoint(); iPoint++) {
117-
solvers[iMesh][HEAT_SOL]->GetNodes()->Set_Solution_time_n1(
118-
iPoint, solvers[iMesh][HEAT_SOL]->GetNodes()->GetSolution_Old(iPoint));
93+
94+
/*--- Finally, place the loaded solution in the correct place (n or n-1 depending on order). ---*/
95+
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
96+
auto* heatSol = solvers[iMesh][HEAT_SOL];
97+
for (auto iPoint = 0ul; iPoint < geometry[val_iZone][val_iInst][iMesh]->GetnPoint(); iPoint++) {
98+
if (dual_time_2nd) {
99+
/*--- If required also move timestep n-1 to timestep n. ---*/
100+
heatSol->GetNodes()->Set_Solution_time_n(iPoint, heatSol->GetNodes()->GetSolution_time_n1(iPoint));
101+
heatSol->GetNodes()->Set_Solution_time_n1(iPoint, heatSol->GetNodes()->GetSolution_Old(iPoint));
102+
} else {
103+
heatSol->GetNodes()->Set_Solution_time_n(iPoint, heatSol->GetNodes()->GetSolution_Old(iPoint));
119104
}
120105
}
121106
}
@@ -140,23 +125,23 @@ void CDiscAdjHeatIteration::Preprocess(COutput* output, CIntegration**** integra
140125
void CDiscAdjHeatIteration::LoadUnsteady_Solution(CGeometry**** geometry, CSolver***** solver, CConfig** config,
141126
unsigned short val_iZone, unsigned short val_iInst,
142127
int val_DirectIter) {
128+
auto solvers = solver[val_iZone][val_iInst];
129+
auto geometries = geometry[val_iZone][val_iInst];
143130

144131
if (val_DirectIter >= 0) {
145132
if (rank == MASTER_NODE)
146133
cout << " Loading heat solution from direct iteration " << val_DirectIter << " for zone " << val_iZone << "." << endl;
147134

148-
solver[val_iZone][val_iInst][MESH_0][HEAT_SOL]->LoadRestart(
149-
geometry[val_iZone][val_iInst], solver[val_iZone][val_iInst], config[val_iZone], val_DirectIter, false);
135+
solvers[MESH_0][HEAT_SOL]->LoadRestart(geometries, solvers, config[val_iZone], val_DirectIter, false);
150136
}
151137
else {
152138
/*--- If there is no solution file we set the freestream condition ---*/
153139
if (rank == MASTER_NODE)
154140
cout << " Setting freestream conditions at direct iteration " << val_DirectIter << " for zone " << val_iZone << "." << endl;
155141

156142
for (auto iMesh = 0u; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
157-
solver[val_iZone][val_iInst][iMesh][HEAT_SOL]->SetFreeStream_Solution(config[val_iZone]);
158-
solver[val_iZone][val_iInst][iMesh][HEAT_SOL]->Postprocessing(
159-
geometry[val_iZone][val_iInst][iMesh], solver[val_iZone][val_iInst][iMesh], config[val_iZone], iMesh);
143+
solvers[iMesh][HEAT_SOL]->SetFreeStream_Solution(config[val_iZone]);
144+
solvers[iMesh][HEAT_SOL]->Postprocessing(geometries[iMesh], solvers[iMesh], config[val_iZone], iMesh);
160145
}
161146
}
162147
}
@@ -177,26 +162,28 @@ void CDiscAdjHeatIteration::InitializeAdjoint(CSolver***** solver, CGeometry****
177162

178163
void CDiscAdjHeatIteration::RegisterInput(CSolver***** solver, CGeometry**** geometry, CConfig** config,
179164
unsigned short iZone, unsigned short iInst, RECORDING kind_recording) {
165+
auto solvers0 = solver[iZone][iInst][MESH_0];
166+
auto geometry0 = geometry[iZone][iInst][MESH_0];
180167

181168
if (kind_recording == RECORDING::SOLUTION_VARIABLES || kind_recording == RECORDING::SOLUTION_AND_MESH) {
182169
/*--- Register flow and turbulent variables as input ---*/
183170

184-
solver[iZone][iInst][MESH_0][ADJHEAT_SOL]->RegisterSolution(geometry[iZone][iInst][MESH_0], config[iZone]);
171+
solvers0[ADJHEAT_SOL]->RegisterSolution(geometry0, config[iZone]);
185172

186-
solver[iZone][iInst][MESH_0][ADJHEAT_SOL]->RegisterVariables(geometry[iZone][iInst][MESH_0], config[iZone]);
173+
solvers0[ADJHEAT_SOL]->RegisterVariables(geometry0, config[iZone]);
187174
}
188175
else if (kind_recording == RECORDING::MESH_COORDS) {
189176
/*--- Register node coordinates as input ---*/
190177

191-
geometry[iZone][iInst][MESH_0]->RegisterCoordinates();
178+
geometry0->RegisterCoordinates();
192179
}
193180
else if (kind_recording == RECORDING::MESH_DEFORM) {
194181
/*--- Register the variables of the mesh deformation ---*/
195182
/*--- Undeformed mesh coordinates ---*/
196-
solver[iZone][iInst][MESH_0][ADJMESH_SOL]->RegisterSolution(geometry[iZone][iInst][MESH_0], config[iZone]);
183+
solvers0[ADJMESH_SOL]->RegisterSolution(geometry0, config[iZone]);
197184

198185
/*--- Boundary displacements ---*/
199-
solver[iZone][iInst][MESH_0][ADJMESH_SOL]->RegisterVariables(geometry[iZone][iInst][MESH_0], config[iZone]);
186+
solvers0[ADJMESH_SOL]->RegisterVariables(geometry0, config[iZone]);
200187
}
201188
}
202189

SU2_CFD/src/output/CAdjElasticityOutput.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,19 +246,19 @@ void CAdjElasticityOutput::SetVolumeOutputFields(CConfig *config){
246246

247247
/*--- Sensitivities with respect to initial conditions. ---*/
248248

249-
AddVolumeOutput("SENS_DISP-X", "SensInitialDisp_x", "SENSITIVITY_T0", "sensitivity to the initial x displacement");
250-
AddVolumeOutput("SENS_DISP-Y", "SensInitialDisp_y", "SENSITIVITY_T0", "sensitivity to the initial y displacement");
249+
AddVolumeOutput("SENS_DISP-X", "SensitivityDispN_x", "SENSITIVITY_N", "sensitivity to the previous x displacement");
250+
AddVolumeOutput("SENS_DISP-Y", "SensitivityDispN_y", "SENSITIVITY_N", "sensitivity to the previous y displacement");
251251
if (nDim == 3)
252-
AddVolumeOutput("SENS_DISP-Z", "SensInitialDisp_z", "SENSITIVITY_T0", "sensitivity to the initial z displacement");
252+
AddVolumeOutput("SENS_DISP-Z", "SensitivityDispN_z", "SENSITIVITY_N", "sensitivity to the previous z displacement");
253253

254-
AddVolumeOutput("SENS_VEL-X", "SensInitialVel_x", "SENSITIVITY_T0", "sensitivity to the initial x velocity");
255-
AddVolumeOutput("SENS_VEL-Y", "SensInitialVel_y", "SENSITIVITY_T0", "sensitivity to the initial y velocity");
254+
AddVolumeOutput("SENS_VEL-X", "SensitivityVelN_x", "SENSITIVITY_N", "sensitivity to the previous x velocity");
255+
AddVolumeOutput("SENS_VEL-Y", "SensitivityVelN_y", "SENSITIVITY_N", "sensitivity to the previous y velocity");
256256
if (nDim == 3)
257-
AddVolumeOutput("SENS_VEL-Z", "SensInitialVel_z", "SENSITIVITY_T0", "sensitivity to the initial z velocity");
257+
AddVolumeOutput("SENS_VEL-Z", "SensitivityVelN_z", "SENSITIVITY_N", "sensitivity to the previous z velocity");
258258

259-
AddVolumeOutput("SENS_ACCEL-X", "SensInitialAccel_x", "SENSITIVITY_T0", "sensitivity to the initial x acceleration");
260-
AddVolumeOutput("SENS_ACCEL-Y", "SensInitialAccel_y", "SENSITIVITY_T0", "sensitivity to the initial y acceleration");
259+
AddVolumeOutput("SENS_ACCEL-X", "SensitivityAccelN_x", "SENSITIVITY_N", "sensitivity to the previous x acceleration");
260+
AddVolumeOutput("SENS_ACCEL-Y", "SensitivityAccelN_y", "SENSITIVITY_N", "sensitivity to the previous y acceleration");
261261
if (nDim == 3)
262-
AddVolumeOutput("SENS_ACCEL-Z", "SensInitialAccel_z", "SENSITIVITY_T0", "sensitivity to the initial z acceleration");
262+
AddVolumeOutput("SENS_ACCEL-Z", "SensitivityAccelN_z", "SENSITIVITY_N", "sensitivity to the previous z acceleration");
263263

264264
}

SU2_CFD/src/output/CAdjHeatOutput.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ void CAdjHeatOutput::SetVolumeOutputFields(CConfig *config){
177177
AddVolumeOutput("SENSITIVITY", "Surface_Sensitivity", "SENSITIVITY", "sensitivity in normal direction");
178178
/// END_GROUP
179179

180+
if (!config->GetTime_Domain()) return;
181+
182+
/*--- Sensitivities with respect to initial conditions. ---*/
183+
184+
AddVolumeOutput("SENS_TEMP_N", "SensitivityTempN", "SENSITIVITY_N", "sensitivity to the previous temperature");
185+
if (config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_2ND) {
186+
AddVolumeOutput("SENS_TEMP_N1", "SensitivityTempN1", "SENSITIVITY_N", "sensitivity to the previous-1 temperature");
187+
}
180188
}
181189

182190
void CAdjHeatOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned long iPoint){
@@ -200,6 +208,13 @@ void CAdjHeatOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolve
200208
if (nDim == 3)
201209
SetVolumeOutputValue("SENSITIVITY-Z", iPoint, Node_AdjHeat->GetSensitivity(iPoint, 2));
202210

211+
if (!config->GetTime_Domain()) return;
212+
213+
SetVolumeOutputValue("SENS_TEMP_N", iPoint, Node_AdjHeat->GetSolution_time_n(iPoint, 0));
214+
if (config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_2ND) {
215+
SetVolumeOutputValue("SENS_TEMP_N1", iPoint, Node_AdjHeat->GetSolution_time_n1(iPoint, 0));
216+
}
217+
203218
}
204219

205220
void CAdjHeatOutput::LoadSurfaceData(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned long iPoint, unsigned short iMarker, unsigned long iVertex){

TestCases/parallel_regression_AD.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,19 @@ def main():
421421
test_list.append(pywrapper_Unst_FEA_AD)
422422
pass_list.append(pywrapper_Unst_FEA_AD.run_test())
423423

424+
# Heat solver unsteady AD
425+
pywrapper_Unst_Heat_AD = TestCase('pywrapper_Unst_Heat_AD')
426+
pywrapper_Unst_Heat_AD.cfg_dir = "py_wrapper/custom_heat_flux"
427+
pywrapper_Unst_Heat_AD.cfg_file = "run_ad.py"
428+
pywrapper_Unst_Heat_AD.test_iter = 100
429+
pywrapper_Unst_Heat_AD.test_vals = [0.776365, 0.776430, 1.000003]
430+
pywrapper_Unst_Heat_AD.command = TestCase.Command("mpirun -n 2", "python", "run_ad.py")
431+
pywrapper_Unst_Heat_AD.timeout = 1600
432+
pywrapper_Unst_Heat_AD.tol = 0.00001
433+
pywrapper_Unst_Heat_AD.new_output = False
434+
test_list.append(pywrapper_Unst_Heat_AD)
435+
pass_list.append(pywrapper_Unst_Heat_AD.run_test())
436+
424437
# Flow AD Mesh Displacement Sensitivity
425438
pywrapper_CFD_AD_MeshDisp = TestCase('pywrapper_CFD_AD_MeshDisp')
426439
pywrapper_CFD_AD_MeshDisp.cfg_dir = "py_wrapper/disc_adj_flow/mesh_disp_sens"

0 commit comments

Comments
 (0)