2 from openmdao.api
import Group, ImplicitComponent, ExplicitComponent, AnalysisError
3 import openmdao.api
as om
4 from dafoam
import PYDAFOAM
5 from idwarp
import USMesh
6 from mphys.builder
import Builder
8 from petsc4py
import PETSc
10 from mpi4py
import MPI
11 from mphys.utils.directory_utils
import cd
13 petsc4py.init(sys.argv)
18 DAFoam builder called from runScript.py
25 scenario="aerodynamic",
51 if scenario.lower() ==
"aerodynamic":
54 elif scenario.lower() ==
"aerostructural":
58 elif scenario.lower() ==
"aerothermal":
63 "scenario %s not valid! Options: aerodynamic, aerostructural, and aerothermal" % scenario
114 if groupName
is None:
115 groupName = self.
DASolver.designSurfacesGroup
116 nodes = int(self.
DASolver.getSurfaceCoordinates(groupName=groupName).size / 3)
131 self.options.declare(
"solver", recordable=
False)
132 self.options.declare(
"struct_coupling", default=
False)
133 self.options.declare(
"use_warper", default=
True)
134 self.options.declare(
"thermal_coupling", default=
False)
135 self.options.declare(
"run_directory", default=
"")
155 promotes_outputs=[
"%s_vol_coords" % self.
discipline],
162 promotes_inputs=[
"*"],
163 promotes_outputs=[
"%s_states" % self.
discipline],
171 promotes_outputs=[
"f_aero"],
178 promotes_inputs=[
"*"],
179 promotes_outputs=[
"*"],
185 Pre-coupling group that configures any components that happen before the solver and post-processor.
189 self.options.declare(
"solver", default=
None, recordable=
False)
190 self.options.declare(
"warp_in_solver", default=
None, recordable=
False)
191 self.options.declare(
"thermal_coupling", default=
None, recordable=
False)
205 promotes_outputs=[
"%s_vol_coords" % self.
discipline],
212 promotes_inputs=[
"*"],
213 promotes_outputs=[
"*"],
219 Post-coupling group that configures any components that happen in the post-processor.
223 self.options.declare(
"solver", default=
None, recordable=
False)
234 OpenMDAO component that wraps the DAFoam flow and adjoint solvers
238 self.options.declare(
"solver", recordable=
False)
239 self.options.declare(
"run_directory", default=
"")
265 DASolver.solverAD.initializedRdWTMatrixFree()
269 self.
psi = PETSc.Vec().create(comm=PETSc.COMM_WORLD)
271 self.
psi.setFromOptions()
272 self.
psi.zeroEntries()
275 if DASolver.getOption(
"adjEqnSolMethod") ==
"fixedPoint":
282 local_state_size = DASolver.getNLocalAdjointStates()
283 self.add_output(self.
stateName, distributed=
True, shape=local_state_size, tags=[
"mphys_coupling"])
286 inputDict = DASolver.getOption(
"inputInfo")
287 for inputName
in list(inputDict.keys()):
289 if "solver" in inputDict[inputName][
"components"]:
290 inputType = inputDict[inputName][
"type"]
291 inputSize = DASolver.solver.getInputSize(inputName, inputType)
292 inputDistributed = DASolver.solver.getInputDistributed(inputName, inputType)
293 self.add_input(inputName, distributed=inputDistributed, shape=inputSize, tags=[
"mphys_coupling"])
321 DASolver.set_solver_input(inputs, self.
DVGeo)
325 meshOK = DASolver.solver.checkMesh()
329 DASolver.solver.writeFailedMesh()
330 raise AnalysisError(
"Mesh quality error!")
337 if DASolver.primalFail != 0:
338 raise AnalysisError(
"Primal solution failed!")
343 if DASolver.getOption(
"useMeanStates"):
344 DASolver.solver.meanStatesToStates()
347 if DASolver.getOption(
"useAD")[
"mode"] ==
"forward":
348 DASolver.solverAD.calcPrimalResidualStatistics(
"print")
350 DASolver.solver.calcPrimalResidualStatistics(
"print")
353 states = DASolver.getStates()
357 DASolver.setStates(states)
361 DASolver.solverAD.calcPrimalResidualStatistics(
"calc")
368 def apply_linear(self, inputs, outputs, d_inputs, d_outputs, d_residuals, mode):
375 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
378 category=om.OpenMDAOWarning,
387 DASolver.setStates(outputs[self.
stateName])
398 DASolver.solverAD.calcJacTVecProduct(
410 inputDict = DASolver.getOption(
"inputInfo")
411 for inputName
in list(inputs.keys()):
412 inputType = inputDict[inputName][
"type"]
413 jacInput = inputs[inputName]
414 product = np.zeros_like(jacInput)
415 DASolver.solverAD.calcJacTVecProduct(
424 d_inputs[inputName] += product
432 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
435 category=om.OpenMDAOWarning,
443 adjEqnSolMethod = DASolver.getOption(
"adjEqnSolMethod")
448 dFdW = DASolver.array2Vec(dFdWArray)
455 if adjEqnSolMethod ==
"Krylov":
459 if DASolver.getOption(
"writeMinorIterations"):
460 if DASolver.dRdWTPC
is None or DASolver.ksp
is None:
461 DASolver.dRdWTPC = PETSc.Mat().create(self.comm)
462 DASolver.solver.calcdRdWT(1, DASolver.dRdWTPC)
463 DASolver.ksp = PETSc.KSP().create(self.comm)
464 DASolver.solverAD.createMLRKSPMatrixFree(DASolver.dRdWTPC, DASolver.ksp)
476 if DASolver.getOption(
"writeDeformedFFDs"):
477 if self.
DVGeo is None:
479 "writeDeformedFFDs is set but no DVGeo object found! Please call add_dvgeo in the run script!"
486 if DASolver.getOption(
"writeDeformedConstraints"):
487 if self.
DVCon is None:
489 "writeDeformedConstraints is set but no DVCon object found! Please call add_dvcon in the run script!"
495 if self.comm.rank == 0:
496 print(
"Driver total derivatives for iteration: %d" % self.
solution_counter, flush=
True)
497 print(
"---------------------------------------------", flush=
True)
502 adjPCLag = DASolver.getOption(
"adjPCLag")
503 if DASolver.dRdWTPC
is None or DASolver.ksp
is None or (self.
solution_counter - 1) % adjPCLag == 0:
506 if DASolver.dRdWTPC
is not None:
507 DASolver.dRdWTPC.destroy()
508 DASolver.dRdWTPC = PETSc.Mat().create(self.comm)
509 DASolver.solver.calcdRdWT(1, DASolver.dRdWTPC)
511 if DASolver.ksp
is not None:
512 DASolver.ksp.destroy()
513 DASolver.ksp = PETSc.KSP().create(self.comm)
514 DASolver.solverAD.createMLRKSPMatrixFree(DASolver.dRdWTPC, DASolver.ksp)
519 if not self.
DASolver.getOption(
"adjEqnOption")[
"useNonZeroInitGuess"]:
523 self.
psi = DASolver.array2Vec(d_residuals[self.
stateName].copy())
525 if self.
DASolver.getOption(
"adjEqnOption")[
"dynAdjustTol"]:
532 fail = DASolver.solverAD.solveLinearEqn(DASolver.ksp, dFdW, self.
psi)
534 elif adjEqnSolMethod ==
"fixedPoint":
540 if self.comm.rank == 0:
541 print(
"Driver total derivatives for iteration: %d" % self.
solution_counter, flush=
True)
542 print(
"---------------------------------------------", flush=
True)
545 fail = DASolver.solverAD.runFPAdj(dFdW, self.
psi)
547 raise RuntimeError(
"adjEqnSolMethod=%s not valid! Options are: Krylov or fixedPoint" % adjEqnSolMethod)
550 psi_array = DASolver.vec2Array(self.
psi)
552 DASolver.writeAdjointFields(
"function", solTimeFloat, psi_array)
555 d_residuals[self.
stateName] = DASolver.vec2Array(self.
psi)
559 raise AnalysisError(
"Adjoint solution failed!")
561 def _updateKSPTolerances(self, psi, dFdW, ksp):
571 jacInput = DASolver.getStates()
572 seed = DASolver.vec2Array(psi)
573 DASolver.solverAD.calcJacTVecProduct(
582 rVec = DASolver.array2Vec(rArray)
583 rVec.axpy(-1.0, dFdW)
588 rTol0 = self.
DASolver.getOption(
"adjEqnOption")[
"gmresRelTol"]
589 aTol0 = self.
DASolver.getOption(
"adjEqnOption")[
"gmresAbsTol"]
591 aTolNew = rNorm * rTol0
596 ksp.setTolerances(rtol=0.0, atol=aTolNew, divtol=
None, max_it=
None)
601 Component to get the partitioned initial surface mesh coordinates
605 self.options.declare(
"solver", recordable=
False)
617 coord_size = self.
x_a0.size
622 desc=
"initial aerodynamic surface node coordinates",
623 tags=[
"mphys_coordinates"],
631 desc=
"aerodynamic surface with geom changes",
644 return self.
DASolver.getTriangulatedMeshSurface()
647 return self.
DASolver._getSurfaceSize(groupName)
651 if "x_%s0_points" % self.
discipline in inputs:
660 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
663 category=om.OpenMDAOWarning,
668 if "x_%s0_points" % self.
discipline in d_inputs:
674 DAFoam objective and constraint functions component
678 self.options.declare(
"solver", recordable=
False)
696 self.add_input(self.
stateName, distributed=
True, shape_by_conn=
True, tags=[
"mphys_coupling"])
699 inputDict = DASolver.getOption(
"inputInfo")
700 for inputName
in list(inputDict.keys()):
702 if "function" in inputDict[inputName][
"components"]:
703 inputType = inputDict[inputName][
"type"]
704 inputSize = DASolver.solver.getInputSize(inputName, inputType)
705 inputDistributed = DASolver.solver.getInputDistributed(inputName, inputType)
706 self.add_input(inputName, distributed=inputDistributed, shape=inputSize, tags=[
"mphys_coupling"])
709 functions = self.
DASolver.getOption(
"function")
711 for f_name
in list(functions.keys()):
712 self.add_output(f_name, distributed=
False, shape=1, units=
None)
723 DASolver.setStates(inputs[self.
stateName])
726 DASolver.evalFunctions(funcs)
727 for f_name
in list(outputs.keys()):
728 outputs[f_name] = funcs[f_name]
736 DASolver.setStates(inputs[self.
stateName])
741 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
744 category=om.OpenMDAOWarning,
749 inputDict = DASolver.getOption(
"inputInfo")
750 for functionName
in list(d_outputs.keys()):
752 seed = d_outputs[functionName]
755 if abs(seed) < 1e-12:
758 for inputName
in list(d_inputs.keys()):
762 product = np.zeros_like(jacInput)
763 DASolver.solverAD.calcJacTVecProduct(
774 inputType = inputDict[inputName][
"type"]
775 jacInput = inputs[inputName]
776 product = np.zeros_like(jacInput)
777 DASolver.solverAD.calcJacTVecProduct(
786 d_inputs[inputName] += product
791 OpenMDAO component that wraps the warping.
795 self.options.declare(
"solver", recordable=
False)
805 local_volume_coord_size = DASolver.mesh.getSolverGrid().size
807 self.add_input(
"x_%s" % self.
discipline, distributed=
True, shape_by_conn=
True, tags=[
"mphys_coupling"])
809 "%s_vol_coords" % self.
discipline, distributed=
True, shape=local_volume_coord_size, tags=[
"mphys_coupling"]
817 x_a = inputs[
"x_%s" % self.
discipline].reshape((-1, 3))
818 DASolver.setSurfaceCoordinates(x_a, DASolver.designSurfacesGroup)
819 DASolver.mesh.warpMesh()
820 solverGrid = DASolver.mesh.getSolverGrid()
821 outputs[
"%s_vol_coords" % self.
discipline] = solverGrid
829 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
832 category=om.OpenMDAOWarning,
838 if "%s_vol_coords" % self.
discipline in d_outputs:
840 dxV = d_outputs[
"%s_vol_coords" % self.
discipline]
844 d_inputs[
"x_%s" % self.
discipline] += dxS.flatten()
849 OpenMDAO component that wraps conjugate heat transfer integration
854 self.options.declare(
"solver", recordable=
False)
866 self.add_input(self.
volCoordName, distributed=
True, shape_by_conn=
True, tags=[
"mphys_coupling"])
867 self.add_input(self.
stateName, distributed=
True, shape_by_conn=
True, tags=[
"mphys_coupling"])
870 outputDict = DASolver.getOption(
"outputInfo")
871 for outputName
in list(outputDict.keys()):
873 if "thermalCoupling" in outputDict[outputName][
"components"]:
877 outputDistributed = DASolver.solver.getOutputDistributed(outputName, self.
outputType)
879 outputName, distributed=outputDistributed, shape=self.
outputSize, tags=[
"mphys_coupling"]
898 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
901 category=om.OpenMDAOWarning,
907 for outputName
in list(d_outputs.keys()):
908 seeds = d_outputs[outputName]
912 product = np.zeros_like(jacInput)
913 DASolver.solverAD.calcJacTVecProduct(
918 "thermalCouplingOutput",
926 product = np.zeros_like(jacInput)
927 DASolver.solverAD.calcJacTVecProduct(
932 "thermalCouplingOutput",
941 Calculate coupling surface coordinates based on volume coordinates
946 self.options.declare(
"solver", recordable=
False)
957 self.add_input(self.
volCoordName, distributed=
True, shape_by_conn=
True, tags=[
"mphys_coupling"])
961 outputDict = DASolver.getOption(
"outputInfo")
962 for outputName
in list(outputDict.keys()):
964 if "thermalCoupling" in outputDict[outputName][
"components"]:
965 outputType = outputDict[outputName][
"type"]
966 outputSize = DASolver.solver.getOutputSize(outputName, outputType)
973 raise AnalysisError(
"no thermalCoupling output found!")
979 self.
DASolver.solver.calcCouplingFaceCoords(volCoords, surfCoords)
989 class DAFoamForces(ExplicitComponent):
991 OpenMDAO component that wraps force integration
996 self.options.declare(
"solver", recordable=
False)
1007 self.add_input(self.
volCoordName, distributed=
True, shape_by_conn=
True, tags=[
"mphys_coupling"])
1008 self.add_input(self.
stateName, distributed=
True, shape_by_conn=
True, tags=[
"mphys_coupling"])
1011 outputDict = self.
DASolver.getOption(
"outputInfo")
1012 for outputName
in list(outputDict.keys()):
1014 if "forceCoupling" in outputDict[outputName][
"components"]:
1018 self.add_output(
"f_aero", distributed=
True, shape=outputSize, tags=[
"mphys_coupling"])
1026 forces = np.zeros_like(outputs[
"f_aero"])
1030 outputs[
"f_aero"] = forces
1033 forcesV = forces.reshape((-1, 3))
1034 fXSum = np.sum(forcesV[:, 0])
1035 fYSum = np.sum(forcesV[:, 1])
1036 fZSum = np.sum(forcesV[:, 2])
1037 fXTot = self.comm.allreduce(fXSum, op=MPI.SUM)
1038 fYTot = self.comm.allreduce(fYSum, op=MPI.SUM)
1039 fZTot = self.comm.allreduce(fZSum, op=MPI.SUM)
1041 if self.comm.rank == 0:
1042 print(
"Total force:", flush=
True)
1043 print(
"Fx = %f" % fXTot, flush=
True)
1044 print(
"Fy = %f" % fYTot, flush=
True)
1045 print(
"Fz = %f" % fZTot, flush=
True)
1053 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
1056 category=om.OpenMDAOWarning,
1060 if "f_aero" in d_outputs:
1061 seeds = d_outputs[
"f_aero"]
1065 product = np.zeros_like(jacInput)
1066 DASolver.solverAD.calcJacTVecProduct(
1071 "forceCouplingOutput",
1079 product = np.zeros_like(jacInput)
1080 DASolver.solverAD.calcJacTVecProduct(
1085 "forceCouplingOutput",
1094 Some utility functions
1099 daOptions: dict or list
1100 The daOptions dict from runScript.py. Support more than two dicts
1103 The om.Problem() object
1115 constraintsComp=None,
1116 designVarsComp=None,
1123 Find the design variables that meet the prescribed constraints. This can be used to get a
1124 feasible design to start the optimization. For example, finding the angle of attack and
1125 tail rotation angle that give the target lift and pitching moment. The sizes of cons and
1126 designvars have to be the same.
1127 NOTE: we use the Newton method to find the feasible design.
1130 if self.
comm.rank == 0:
1131 print(
"Finding a feasible design using the Newton method. ")
1132 print(
"Constraints: ", constraints)
1133 print(
"Design Vars: ", designVars)
1134 print(
"Target: ", targets)
1136 if len(constraints) != len(designVars):
1137 raise RuntimeError(
"Sizes of the constraints and designVars lists need to be the same! ")
1139 size = len(constraints)
1142 if constraintsComp
is None:
1143 constraintsComp = size * [0]
1144 if designVarsComp
is None:
1145 designVarsComp = size * [0]
1148 epsFD = size * [1e-3]
1150 if maxNewtonStep
is None:
1151 maxNewtonStep = size * [1e16]
1154 for n
in range(maxIter):
1157 jacMat = np.zeros((size, size))
1163 dv0 = np.zeros(size)
1164 for i
in range(size):
1165 dvName = designVars[i]
1166 comp = designVarsComp[i]
1167 val = self.
om_prob.get_val(dvName)
1169 con0 = np.zeros(size)
1170 for i
in range(size):
1171 conName = constraints[i]
1172 comp = constraintsComp[i]
1173 val = self.
om_prob.get_val(conName)
1177 res = con0 - targets
1180 norm = np.linalg.norm(res / targets)
1182 if self.
comm.rank == 0:
1183 print(
"FindFeasibleDesign Iter: ", n, flush=
True)
1184 print(
"DesignVars: ", dv0, flush=
True)
1185 print(
"Constraints: ", con0, flush=
True)
1186 print(
"Residual Norm: ", norm, flush=
True)
1190 if self.
comm.rank == 0:
1191 print(
"FindFeasibleDesign Converged! ", flush=
True)
1195 for i
in range(size):
1196 dvName = designVars[i]
1197 comp = designVarsComp[i]
1199 dvP = dv0[i] + epsFD[i]
1200 self.
om_prob.set_val(dvName, dvP, indices=comp)
1204 self.
om_prob.set_val(dvName, dv0[i], indices=comp)
1207 for j
in range(size):
1208 conName = constraints[j]
1209 comp = constraintsComp[j]
1210 val = self.
om_prob.get_val(conName)
1213 deriv = (conP - con0[j]) / epsFD[i]
1214 jacMat[j][i] = deriv
1217 deltaDV = -np.linalg.inv(jacMat).dot(res)
1220 for i
in range(size):
1221 if abs(deltaDV[i]) > abs(maxNewtonStep[i]):
1223 deltaDV[i] = abs(maxNewtonStep[i])
1225 deltaDV[i] = -abs(maxNewtonStep[i])
1229 for i
in range(size):
1230 dvName = designVars[i]
1231 comp = designVarsComp[i]
1232 self.
om_prob.set_val(dvName, dv1[i], indices=comp)
1238 self.options.declare(
"solver_options")
1239 self.options.declare(
"mesh_options", default=
None)
1240 self.options.declare(
"run_directory", default=
"")
1252 mesh = USMesh(options=self.
mesh_options, comm=self.comm)
1259 inputDict = self.
DASolver.getOption(
"inputInfo")
1260 for inputName
in list(inputDict.keys()):
1262 if "solver" in inputDict[inputName][
"components"]:
1263 inputType = inputDict[inputName][
"type"]
1264 if inputType ==
"volCoord":
1278 self.options.declare(
"solver")
1279 self.options.declare(
"run_directory", default=
"")
1292 raise AnalysisError(
"adjEqnSolMethod is not valid")
1294 inputDict = DASolver.getOption(
"inputInfo")
1295 for inputName
in list(inputDict.keys()):
1297 if "solver" in inputDict[inputName][
"components"]:
1298 inputType = inputDict[inputName][
"type"]
1299 inputSize = DASolver.solver.getInputSize(inputName, inputType)
1300 inputDistributed = DASolver.solver.getInputDistributed(inputName, inputType)
1301 self.add_input(inputName, distributed=inputDistributed, shape=inputSize)
1307 raise AnalysisError(
"unsteadyCompOutput is not defined for unsteady cases")
1309 functions = DASolver.getOption(
"function")
1312 self.add_output(outputName, distributed=0, shape=1)
1316 if funcName
not in functions:
1317 raise AnalysisError(
"%f is not found in DAOption-function" % funcName)
1331 readZeroFields = DASolver.getOption(
"unsteadyAdjoint")[
"readZeroFields"]
1333 DASolver.solver.setTime(0.0, 0)
1334 deltaT = DASolver.solver.getDeltaT()
1335 DASolver.readStateVars(0.0, deltaT)
1339 DASolver.set_solver_input(inputs, self.
DVGeo)
1341 DASolver.deformDynamicMesh()
1345 meshOK = DASolver.solver.checkMesh()
1354 raise AnalysisError(
"Primal mesh failed!")
1358 if DASolver.primalFail != 0:
1359 raise AnalysisError(
"Primal solution failed!")
1364 DASolver.evalFunctions(funcs)
1367 DASolver.solver.calcPrimalResidualStatistics(
"print")
1370 outputs[outputName] = 0.0
1373 outputs[outputName] += funcs[funcName]
1378 " mode = %s, but the forward mode functions are not implemented for DAFoam!" % mode,
1381 category=om.OpenMDAOWarning,
1389 DASolver.solver.runColoring()
1391 PCMatPrecomputeInterval = DASolver.getOption(
"unsteadyAdjoint")[
"PCMatPrecomputeInterval"]
1392 PCMatUpdateInterval = DASolver.getOption(
"unsteadyAdjoint")[
"PCMatUpdateInterval"]
1396 DASolver.solverAD.updateStateBoundaryConditions()
1397 DASolver.solverAD.calcPrimalResidualStatistics(
"calc")
1402 deltaT = DASolver.solver.getDeltaT()
1404 endTime = DASolver.solver.getEndTime()
1405 endTimeIndex = round(endTime / deltaT)
1407 localAdjSize = DASolver.getNLocalAdjointStates()
1409 ddtSchemeOrder = DASolver.solver.getDdtSchemeOrder()
1412 DASolver.solver.setTime(endTime, endTimeIndex)
1413 DASolver.solverAD.setTime(endTime, endTimeIndex)
1415 DASolver.readStateVars(endTime, deltaT)
1417 if DASolver.getOption(
"dynamicMesh")[
"active"]:
1418 DASolver.readDynamicMeshPoints(endTime, deltaT, endTimeIndex, ddtSchemeOrder)
1421 DASolver.solverAD.calcPrimalResidualStatistics(
"print")
1425 DASolver.solverAD.initializedRdWTMatrixFree()
1433 DASolver.solver.setTime(endTime, endTimeIndex)
1434 DASolver.solverAD.setTime(endTime, endTimeIndex)
1436 DASolver.readStateVars(endTime, deltaT)
1438 if DASolver.getOption(
"dynamicMesh")[
"active"]:
1439 DASolver.readDynamicMeshPoints(endTime, deltaT, endTimeIndex, ddtSchemeOrder)
1441 if self.comm.rank == 0:
1442 print(
"Pre-Computing preconditiner mat for t = %f" % endTime, flush=
True)
1444 dRdWTPC1 = PETSc.Mat().create(PETSc.COMM_WORLD)
1445 DASolver.solver.calcdRdWT(1, dRdWTPC1)
1448 self.
dRdWTPC[str(endTime)] = dRdWTPC1
1452 for timeIndex
in range(endTimeIndex - 1, 0, -1):
1453 if timeIndex % PCMatPrecomputeInterval == 0:
1454 t = timeIndex * deltaT
1455 if self.comm.rank == 0:
1456 print(
"Pre-Computing preconditiner mat for t = %f" % t, flush=
True)
1458 DASolver.solver.setTime(t, timeIndex)
1459 DASolver.solverAD.setTime(t, timeIndex)
1461 DASolver.readStateVars(t, deltaT)
1463 if DASolver.getOption(
"dynamicMesh")[
"active"]:
1464 DASolver.readDynamicMeshPoints(t, deltaT, timeIndex, ddtSchemeOrder)
1466 dRdWTPC1 = PETSc.Mat().create(PETSc.COMM_WORLD)
1467 DASolver.solver.calcdRdWT(1, dRdWTPC1)
1470 self.
dRdWTPC[str(t)] = dRdWTPC1
1474 PCMat = self.
dRdWTPC[str(endTime)]
1475 ksp = PETSc.KSP().create(PETSc.COMM_WORLD)
1476 DASolver.solverAD.createMLRKSPMatrixFree(PCMat, ksp)
1478 inputDict = DASolver.getOption(
"inputInfo")
1481 dFdW = PETSc.Vec().create(PETSc.COMM_WORLD)
1482 dFdW.setSizes((localAdjSize, PETSc.DECIDE), bsize=1)
1483 dFdW.setFromOptions()
1487 psi = dFdW.duplicate()
1491 dRdW0TPsi = np.zeros(localAdjSize)
1492 dRdW00TPsi = np.zeros(localAdjSize)
1493 dRdW00TPsiBuffer = np.zeros(localAdjSize)
1494 dFdWArray = np.zeros(localAdjSize)
1495 psiArray = np.zeros(localAdjSize)
1496 tempdFdWArray = np.zeros(localAdjSize)
1504 for inputName
in list(inputs.keys()):
1505 totals[inputName] = np.zeros_like(inputs[inputName])
1507 seed = d_outputs[outputName]
1511 if np.linalg.norm(seed) < 1e-12:
1517 dRdW00TPsiBuffer[:] = 0.0
1522 for n
in range(endTimeIndex, 0, -1):
1523 timeVal = n * deltaT
1525 if self.comm.rank == 0:
1526 print(
"---- Solving unsteady adjoint for %s. t = %f ----" % (outputName, timeVal), flush=
True)
1531 DASolver.solver.setTime(timeVal, n)
1532 DASolver.solverAD.setTime(timeVal, n)
1535 DASolver.readStateVars(timeVal, deltaT)
1537 if DASolver.getOption(
"dynamicMesh")[
"active"]:
1538 DASolver.readDynamicMeshPoints(timeVal, deltaT, n, ddtSchemeOrder)
1547 dFScaling = DASolver.solver.getdFScaling(firstFunctionName, n - 1)
1555 jacInput = DASolver.getStates()
1556 DASolver.solverAD.calcJacTVecProduct(
1566 dFdWArray += tempdFdWArray * dFScaling
1569 if ddtSchemeOrder == 1:
1570 dFdWArray = dFdWArray - dRdW0TPsi
1571 elif ddtSchemeOrder == 2:
1572 dFdWArray = dFdWArray - dRdW0TPsi - dRdW00TPsi
1574 dRdW00TPsi[:] = dRdW00TPsiBuffer
1576 print(
"ddtSchemeOrder not valid!" % ddtSchemeOrder)
1580 if str(timeVal)
in list(self.
dRdWTPC.keys()):
1581 if self.comm.rank == 0:
1582 print(
"Using pre-computed KSP PC mat for %f" % timeVal, flush=
True)
1583 PCMat = self.
dRdWTPC[str(timeVal)]
1584 DASolver.solverAD.updateKSPPCMat(PCMat, ksp)
1585 if n % PCMatUpdateInterval == 0
and n < endTimeIndex:
1587 if self.comm.rank == 0:
1588 print(
"Updating dRdWTPC mat value using OF fvMatrix", flush=
True)
1589 DASolver.solver.calcPCMatWithFvMatrix(PCMat)
1592 DASolver.arrayVal2Vec(dFdWArray, dFdW)
1595 adjointFail = DASolver.solverAD.solveLinearEqn(ksp, dFdW, psi)
1597 adjointFail = DASolver.solverAD.solveAdjointFP(dFdW, psi)
1604 for inputName
in list(inputs.keys()):
1607 inputType = inputDict[inputName][
"type"]
1608 jacInput = inputs[inputName]
1609 dFdX = np.zeros_like(jacInput)
1610 tempdFdX = np.zeros_like(jacInput)
1615 DASolver.solverAD.calcJacTVecProduct(
1625 dFdX += tempdFdX * dFScaling
1628 dRdXTPsi = np.zeros_like(jacInput)
1629 DASolver.vecVal2Array(psi, psiArray)
1630 DASolver.solverAD.calcJacTVecProduct(
1641 totals[inputName] += dFdX - dRdXTPsi
1644 if ddtSchemeOrder == 1:
1645 DASolver.solverAD.calcdRdWOldTPsiAD(1, psiArray, dRdW0TPsi)
1646 elif ddtSchemeOrder == 2:
1649 DASolver.solverAD.calcdRdWOldTPsiAD(1, psiArray, dRdW0TPsi)
1650 DASolver.solverAD.calcdRdWOldTPsiAD(2, psiArray, dRdW00TPsiBuffer)
1652 for inputName
in list(inputs.keys()):
1653 d_inputs[inputName] += totals[inputName]
1658 DASolver.solver.setTime(endTime, endTimeIndex)
1659 DASolver.solverAD.setTime(endTime, endTimeIndex)
1660 DASolver.readStateVars(endTime, deltaT)