Skip to content

Commit

Permalink
added rootSetOption and error estimation (#220)
Browse files Browse the repository at this point in the history
* added rootSetOption

* added solveErrorEstimate

* added tests

* addressed comments

* updated rootSetOptions

* loosened tolerance

* version bump

* fix another typo

* loosened tolerance

* updated docstrings

* changed tolerance

* updated docstrings again
  • Loading branch information
ewu63 committed May 22, 2022
1 parent bb0b139 commit 4b179a0
Show file tree
Hide file tree
Showing 5 changed files with 656 additions and 2 deletions.
2 changes: 1 addition & 1 deletion adflow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.7.3"
__version__ = "2.7.4"

from mpi4py import MPI

Expand Down
80 changes: 79 additions & 1 deletion adflow/pyADflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"):
self.optionMap, self.moduleMap = self._getOptionMap()
self.pythonOptions, deprecatedOptions, self.specialOptions = self._getSpecialOptionLists()
immutableOptions = self._getImmutableOptions()
self.rootChangedOptions = {}

self.possibleAeroDVs, self.possibleBCDvs, self.basicCostFunctions = self._getObjectivesAndDVs()

Expand Down Expand Up @@ -981,7 +982,9 @@ def __call__(self, aeroProblem, **kwargs):
is used in a multidisciplinary environment when the outer
solver can suppress all I/O during intermediate solves.
"""

self.rootChangedOptions = self.comm.bcast(self.rootChangedOptions, root=0)
for key, val in self.rootChangedOptions.items():
self.setOption(key, val)
startCallTime = time.time()

# Get option about adjoint memory
Expand Down Expand Up @@ -4656,6 +4659,59 @@ def getResidual(self, aeroProblem, res=None, releaseAdjointMemory=True):

return res

def solveErrorEstimate(self, aeroProblem, funcError, evalFuncs=None):
r"""
Evaluate the desired function errors given in iterable object
'evalFuncs', and add them to the dictionary 'funcError'. The keys
in the funcError dictionary will be have an ``<ap.name>_`` prepended to them.
Parameters
----------
aeroProblem : pyAero_problem class
The aerodynamic problem to get the error for
funcError : dict
Dictionary into which the function errors are saved.
We define error to be :math:`\epsilon = f^\ast - f`, where
:math:`f^\ast` is the converged solution and :math:`f` is the unconverged solution.
evalFuncs : iterable object containing strings
If not None, use these functions to evaluate.
Examples
--------
>>> CFDsolver(ap)
>>> funcsSens = {}
>>> CFDSolver.evalFunctionsSens(ap, funcsSens)
>>> funcError = {}
>>> CFDsolver.solveErrorEstimate(ap, funcError)
>>> # Result will look like (if aeroProblem, ap, has name of 'wing'):
>>> print(funcError)
>>> # {'wing_cl':0.00085, 'wing_cd':0.000021}
"""
self.setAeroProblem(aeroProblem)
res = self.getResidual(aeroProblem)
if evalFuncs is None:
evalFuncs = sorted(self.curAP.evalFuncs)

# Make sure we have a list that has only lower-cased entries
tmp = []
for f in evalFuncs:
tmp.append(f.lower())
evalFuncs = tmp

# Do the functions one at a time:
for f in evalFuncs:

key = f"{self.curAP.name}_{f}"

# Set dict structure for this derivative
psi = self.getAdjoint(f)
error = numpy.dot(psi, res)
errorTot = self.comm.allreduce(error)
errorTot = -1 * errorTot # multiply by -1 so that estimate is added to current output
funcError[key] = errorTot

def getFreeStreamResidual(self, aeroProblem):
self.setAeroProblem(aeroProblem)
rhoRes, totalRRes = self.adflow.nksolver.getfreestreamresidual()
Expand All @@ -4675,6 +4731,28 @@ def _getSurfaceSize(self, groupName, includeZipper=True):
[nPts, nCells] = self.adflow.surfaceutils.getsurfacesize(self.families[groupName], includeZipper)
return nPts, nCells

def rootSetOption(self, name, value, reset=False):
"""
Set ADflow options from the root proc.
The option will be broadcast to all procs when __call__ is invoked.
Parameters
----------
name : str
The name of the option
value : Any
The value of the option
reset : Bool
If True, we reset all previously-set rootChangedOptions.
See Also
--------
:func: setOption
"""
if reset:
self.rootChangedOptions = {}
self.rootChangedOptions[name] = value

def setOption(self, name, value):
"""
Set Solver Option Value
Expand Down
235 changes: 235 additions & 0 deletions tests/reg_tests/refs/error_euler_wing_full.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
{
"errors": {
"mdo_tutorial_cd": 4.461715234198106e-16,
"mdo_tutorial_cl": -9.6153107436299e-15,
"mdo_tutorial_cmz": -1.0473464896718247e-14,
"mdo_tutorial_drag": 1.8189520666778846e-10,
"mdo_tutorial_fx": 3.0493468198221515e-10,
"mdo_tutorial_lift": -3.919969883963042e-09,
"mdo_tutorial_mz": -1.3876922049555845e-08
},
"metadata": {
"ADPC": false,
"AGMGLevels": 1,
"AGMGNSmooth": 3,
"ANKADPC": false,
"ANKASMOverlap": 1,
"ANKCFL0": 5.0,
"ANKCFLCutback": 0.5,
"ANKCFLExponent": 0.5,
"ANKCFLFactor": 10.0,
"ANKCFLLimit": 100000.0,
"ANKCFLMin": 1.0,
"ANKConstCFLStep": 0.4,
"ANKCoupledSwitchTol": 1e-16,
"ANKInnerPreconIts": 1,
"ANKJacobianLag": 10,
"ANKLinResMax": 0.1,
"ANKLinearSolveTol": 0.05,
"ANKMaxIter": 40,
"ANKNSubiterTurb": 1,
"ANKOuterPreconIts": 1,
"ANKPCILUFill": 2,
"ANKPCUpdateTol": 0.5,
"ANKPhysicalLSTol": 0.2,
"ANKPhysicalLSTolTurb": 0.99,
"ANKSecondOrdSwitchTol": 1e-16,
"ANKStepFactor": 1.0,
"ANKStepMin": 0.01,
"ANKSubspaceSize": -1,
"ANKSwitchTol": 1000.0,
"ANKTurbCFLScale": 1.0,
"ANKTurbKSPDebug": false,
"ANKUnsteadyLSTol": 1.0,
"ANKUseFullVisc": true,
"ANKUseMatrixFree": true,
"ANKUseTurbDADI": true,
"ASMOverlap": 1,
"CFL": 1.7,
"CFLCoarse": 1.0,
"CFLLimit": 1.5,
"GMRESOrthogonalizationType": "modified Gram-Schmidt",
"ILUFill": 2,
"L2Convergence": 1e-14,
"L2ConvergenceCoarse": 0.01,
"L2ConvergenceRel": 1e-16,
"MGCycle": "sg",
"MGStartLevel": -1,
"NKADPC": false,
"NKASMOverlap": 1,
"NKFixedStep": 0.25,
"NKInnerPreconIts": 1,
"NKJacobianLag": 20,
"NKLS": "cubic",
"NKLinearSolveTol": 0.3,
"NKOuterPreconIts": 1,
"NKPCILUFill": 2,
"NKSubspaceSize": 60,
"NKSwitchTol": 1e-05,
"NKUseEW": true,
"NKViscPC": false,
"RKReset": false,
"TSStability": false,
"adjointDivTol": 100000.0,
"adjointL2Convergence": 1e-14,
"adjointL2ConvergenceAbs": 1e-16,
"adjointL2ConvergenceRel": 1e-16,
"adjointMaxIter": 500,
"adjointMaxL2DeviationFactor": 1.0,
"adjointMonitorStep": 10,
"adjointSolver": "GMRES",
"adjointSubspaceSize": 100,
"alphaFollowing": true,
"alphaMode": false,
"altitudeMode": false,
"applyAdjointPCSubspaceSize": 20,
"applyPCSubspaceSize": 10,
"approxPC": true,
"backgroundVolScale": 1.0,
"betaMode": false,
"blockSplitting": true,
"cavitationNumber": 1.4,
"closedSurfaceFamilies": null,
"coarseDiscretization": "central plus scalar dissipation",
"computeCavitation": false,
"coupledSolution": false,
"cutCallback": null,
"debugZipper": false,
"deltaT": 0.01,
"designSurfaceFamily": null,
"discretization": "central plus scalar dissipation",
"dissipationLumpingParameter": 6.0,
"dissipationScalingExponent": 0.67,
"eddyVisInfRatio": 0.009,
"equationMode": "steady",
"equationType": "Euler",
"eulerWallTreatment": "linear pressure extrapolation",
"firstRun": true,
"flowType": "external",
"forcesAsTractions": true,
"frozenTurbulence": false,
"globalPreconditioner": "additive Schwarz",
"gridFile": "input_files/mdo_tutorial_euler_scalar_jst.cgns",
"gridPrecision": "double",
"gridPrecisionSurface": "single",
"infChangeCorrection": true,
"innerPreconIts": 1,
"isoVariables": [],
"isosurface": {},
"liftIndex": 2,
"limiter": "van Albada",
"loadBalanceIter": 10,
"loadImbalance": 0.1,
"localPreconditioner": "ILU",
"lowSpeedPreconditioner": false,
"machMode": false,
"matrixOrdering": "RCM",
"maxL2DeviationFactor": 1.0,
"meshSurfaceFamily": null,
"monitorVariables": [
"cpu",
"resrho",
"resturb",
"cl",
"cd"
],
"nCycles": 2000,
"nCyclesCoarse": 500,
"nFloodIter": -1,
"nRKReset": 5,
"nRefine": 10,
"nSaveSurface": 1,
"nSaveVolume": 1,
"nSubiter": 1,
"nSubiterTurb": 3,
"nTimeStepsCoarse": 48,
"nTimeStepsFine": 400,
"nearWallDist": 0.1,
"numberSolutions": true,
"outerPreconIts": 3,
"outputDirectory": "tests/output_files",
"outputSurfaceFamily": "allSurfaces",
"overlapFactor": 0.9,
"oversetLoadBalance": true,
"oversetPriority": {},
"oversetProjTol": 1e-12,
"oversetUpdateMode": "frozen",
"pMode": false,
"partitionLikeNProc": -1,
"partitionOnly": false,
"preconditionerSide": "right",
"printAllOptions": true,
"printIntro": true,
"printIterations": true,
"printTiming": true,
"printWarnings": true,
"qMode": false,
"rMode": false,
"resAveraging": "alternate",
"restartAdjoint": true,
"restartFile": "input_files/mdo_tutorial_euler_scalar_jst.cgns",
"restrictionRelaxation": 0.8,
"selfZipCutoff": 120.0,
"sepSensorOffset": 0.0,
"sepSensorSharpness": 10.0,
"setMonitor": true,
"skipAfterFailedAdjoint": true,
"smoothParameter": 1.5,
"smoother": "Runge-Kutta",
"solutionPrecision": "single",
"solutionPrecisionSurface": "single",
"storeConvHist": true,
"storeRindLayer": true,
"surfaceVariables": [
"cp",
"vx",
"vy",
"vz",
"mach"
],
"timeAccuracy": 2,
"timeIntegrationScheme": "BDF",
"timeIntervals": 1,
"timeLimit": -1.0,
"turbResScale": 10000.0,
"turbulenceModel": "SA",
"turbulenceOrder": "first order",
"turbulenceProduction": "strain",
"useALE": true,
"useANKSolver": true,
"useApproxWallDistance": true,
"useBlockettes": true,
"useDiagTSPC": true,
"useExternalDynamicMesh": false,
"useGridMotion": false,
"useLinResMonitor": false,
"useMatrixFreedrdw": true,
"useNKSolver": true,
"useOversetWallScaling": false,
"useQCR": false,
"useRotationSA": false,
"useTSInterpolatedGridVelocity": false,
"useWallFunctions": false,
"useZipperMesh": true,
"useft2SA": true,
"verifyExtra": true,
"verifySpatial": true,
"verifyState": true,
"vis2": 0.25,
"vis2Coarse": 0.5,
"vis4": 0.0156,
"viscPC": false,
"viscWallTreatment": "constant pressure extrapolation",
"viscousSurfaceVelocities": true,
"volumeVariables": [
"resrho"
],
"wallDistCutoff": 1e+20,
"windAxis": false,
"writeSolutionEachIter": false,
"writeSurfaceSolution": true,
"writeTecplotSurfaceSolution": false,
"writeVolumeSolution": true,
"zipperSurfaceFamily": null
}
}

0 comments on commit 4b179a0

Please sign in to comment.