From e201e79fc762dd95e4fc5cc98b08687e5b8409e8 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Mon, 15 Apr 2024 20:05:14 -0400 Subject: [PATCH 01/49] Modify pyADflow.py for the propeller model --- adflow/pyADflow.py | 122 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 22 deletions(-) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 932a46ad4..92f3baeb7 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -877,19 +877,43 @@ def addIntegrationSurface(self, fileName, familyName, isInflow=True, coordXfer=N def addActuatorRegion( self, fileName, + actType, axis1, axis2, familyName, thrust=0.0, torque=0.0, - heat=0.0, + # heat=0.0, + swirlFact=0.0, + mDistribParam=1.0, + nDistribParam=0.5, + distribPDfactor=0.5, + innerZeroThrustRadius=0.0, + propRadius=0.1, + spinnerRadius=0.0, + rootDragFactor=0.0, relaxStart=None, relaxEnd=None, - coordXfer=None, + coordXfer=None ): - """ - Add an actuator disk zone defined by the supplied closed surface in the - plot3d file "fileName". This surface defines the physical extent of the + """Add an actuator zone with a uniform force distribution or add + an actuator-disk zone representing a propeller. The zone is defined by + the (closed) supplied surface in the plot3d file "fileName". The type + is set with the string "actType" as either 'uniform' or 'simpleProp'. + + For the uniform distribution (i.e., actType = 'uniform'): + The specified thrust is applied uniformly over the specified zone. + + For the propeller model (i.e., actType = 'simpleProp'): + The radial distributions of the axial and tangential forces can be tuned + using the parameters. For the distributions, the models used by Hoekstra + in "A RANS-based analysis tool for ducted propeller systems in open water + condition" [International Shipbuilding Progress, 2006] are used here. + See "RANS-based aerodynamic shape optimization of a wing considering + propeller-wing interaction" by Chauhan and Martins + for more. This applies axis-symmetric (but radially varying) forces. + + The surface defines the physical extent of the region over which to apply the source terms. The plot3d file may be multi-block but all the surface normals must point outside and no additional surfaces can be inside. Internally, we find all of the CFD @@ -934,29 +958,41 @@ def addActuatorRegion( ---------- fileName : str - Surface Plot 3D file (multiblock ascii) defining the closed - region over which the integration is to be applied. + The surface Plot3D file (multiblock ascii) defining the closed + region to which the forces are to be applied. + + actType : str + The type of force distribution. + Uniform ('uniform') or propeller ('simpleProp'). axis1 : numpy array, length 3 - The physical location of the start of the axis + The physical location of the start of the thrust or propeller axis (x,y,z). - axis2 : numpy array, length 4 - The physical location of the end of the axis + axis2 : numpy array, length 3 + The physical location of the end of the thrust or propeller axis (x,y,z). + The axis1 and axis2 points are used to define the direction of the + thrust, and also to define the propeller axis for the propeller model. + The propeller axis is used to compute the radii of the cells in the + actuator-disk zone and also to calculate the directions for axial and + tangential forces. familyName : str - The name to be associated with the functions defined on this - region. + The name to be associated with the functions defined on this region. - thrust : scalar, float - The total amount of axial force to apply to this region, in the direction - of axis1 -> axis2 + thrust : scalar + The total magnitude of the (axial) thrust to apply to the region, + in the direction of axis1 -> axis2. (This does not include the forces + applied inside the innerZeroThrustRadius for the propeller model. + See below for a description of innerZeroThrustRadius.) - torque : scalar, float + torque : scalar The total amount of torque to apply to the region, about the - specified axis. + specified axis. This is only for the uniform actuator zone. - heat : scalar, float - The total amount of head added in the actuator zone with source terms + # ----- Shamsheer note: This is new in the mdolab ADflow. If needed, incorporate later. ------- + # heat : scalar, float + # The total amount of head added in the actuator zone with source terms + # --------------------------------------------------------------------------------------------- relaxStart : scalar, float The start of the relaxation in terms of @@ -973,6 +1009,42 @@ def addActuatorRegion( arbitrary modifications to the loaded plot3d surface. The call signature is documented in DVGeometry's :meth:`addPointset ` method. + Note that the following are only for the propeller model. + + swirlFact : scalar + A factor to multiply the tangential forces by. For example, this can + be used to reverse the swirl rotation direction or remove the swirl. + If axis1 -> axis2 points front to back, then a positive swirlFact will + give a clockwise rotation looking from the back. + + mDistribParam : scalar + The m parameter in the distribution. See the Hoekstra or Chauhan and + Martins papers mentioned above. + + nDistribParam : scalar + The n parameter for the distribution. See the Hoekstra or Chauhan and + Martins papers mentioned above. + + distribPDfactor : scalar + The pitch-to-diameter ratio for the blade. See the Hoekstra or + Chauhan and Martins papers mentioned above. Increasing the pitch-to- + diameter ratio increases the swirl. + + innerZeroThrustRadius : scalar + The radius at which the thrust becomes zero and then goes negative. + Only use this if you know the propeller produces drag near the root, + otherwise use the default value of 0. + + propRadius : scalar + The outer radius of the propeller. + + spinnerRadius : scalar + The radius at which the blades connect to the spinner (aka the hub). + + rootDragFactor : scalar + A factor that the negative thrust (drag) inside the innerZeroThrustRadius + is multiplied by. This is used to scale the forces in the region. + This is not required if not using the innerZeroThrustRadius. """ # ActuatorDiskRegions cannot be used in timeSpectralMode if self.getOption("equationMode").lower() == "time spectral": @@ -1014,10 +1086,16 @@ def addActuatorRegion( if relaxEnd is None and relaxStart is not None: raise Error("relaxEnd must be given is relaxStart is specified") - # Now continue to fortran were we setup the actual actuator region. + if actType != 'uniform' and actType != 'simpleProp': + raise Error("actType must be 'uniform' or 'simpleProp'") + + # Now continue to fortran were we setup the actual region. self.adflow.actuatorregion.addactuatorregion( - pts.T, conn.T, axis1, axis2, familyName, famID, thrust, torque, heat, relaxStart, relaxEnd - ) + pts.T, conn.T, actType, axis1, axis2, familyName, famID, thrust, torque, + # heat + swirlFact, + mDistribParam, nDistribParam, distribPDfactor, innerZeroThrustRadius, + propRadius, spinnerRadius, rootDragFactor, relaxStart, relaxEnd) def writeActuatorRegions(self, fileName, outputDir=None): """ From a9730f6c140fb5f2dc362b81e067b41251aaeb65 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Tue, 16 Apr 2024 18:02:20 -0400 Subject: [PATCH 02/49] Modify adflow.pyf for the propeller model --- src/f2py/adflow.pyf | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index c666338fc..2b2870df0 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -677,16 +677,26 @@ python module libadflow end module usersurfaceintegrations module actuatorregion ! in :test:actuatorDiskRegion.F90 - subroutine addactuatorregion(pts,conn,axis1,axis2,famname,famid,thrust,torque,heat,relaxstart,relaxend,npts,nconn) ! in :test:actuatorDiskRegion.F90:actuatorregion + subroutine addactuatorregion(pts,conn,acttype,axis1,axis2,famname,famid,thrust,torque,swirlfact,mdistribparam,ndistribparam,distribpdfactor,innerzerothrustradius,propradius,spinnerradius,rootdragfactor,relaxstart,relaxend,npts,nconn) ! in :test:actuatorDiskRegion.F90:actuatorregion real(kind=realtype) dimension(3,npts),intent(in) :: pts integer(kind=inttype) dimension(4,nconn),intent(in) :: conn + character*(*) :: acttype real(kind=realtype), dimension(3),intent(in) :: axis1 real(kind=realtype), dimension(3),intent(in) :: axis2 character*(*) :: famname integer(kind=inttype) intent(in) :: famid real(kind=realtype) :: thrust real(kind=realtype) :: torque - real(kind=realtype) :: heat + !# Shamsheer commented out heat and removed from the subroutine line above. + !# real(kind=realtype) :: heat + real(kind=realtype) :: swirlfact + real(kind=realtype) :: mdistribparam + real(kind=realtype) :: ndistribparam + real(kind=realtype) :: distribpdfactor + real(kind=realtype) :: innerzerothrustradius + real(kind=realtype) :: propradius + real(kind=realtype) :: spinnerradius + real(kind=realtype) :: rootdragfactor real(kind=realtype) :: relaxstart real(kind=realtype) :: relaxend integer(kind=inttype), optional,intent(in),check(shape(pts,1)==npts),depend(pts) :: npts=shape(pts,1) From 20cba1f1cbc32f18039e0132dddc82f9b11b50a7 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Wed, 17 Apr 2024 16:44:07 -0400 Subject: [PATCH 03/49] Modify actuatorRegionData.F90 for the propeller model --- src/modules/actuatorRegionData.F90 | 38 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/modules/actuatorRegionData.F90 b/src/modules/actuatorRegionData.F90 index b49d82c89..539233776 100644 --- a/src/modules/actuatorRegionData.F90 +++ b/src/modules/actuatorRegionData.F90 @@ -3,30 +3,50 @@ module actuatorRegionData type actuatorRegionType - character(len=maxStringLen) :: famName + character(len=maxStringLen) :: famName, actType integer(kind=intType) :: famID ! The block indexes of the cells included in this region integer(kind=intType), dimension(:, :), pointer :: cellIDs + ! The tangent unit-vectors of the cells included in this region + real(kind=realType), dimension(:, :), pointer :: cellTangentials + ! The radii of the cells included in this region + real(kind=realType), dimension(:), pointer :: cellRadii + ! The total number of cells included this proc has integer(kind=intType) :: nCellIDs - ! the force vector to be applied on this region - ! this is equal to torque * axisVec - real(kind=realType) :: force(3) + ! F is the total Force to be applied on this region + real(kind=realType) :: F(3) + + ! thrust is the total thrust magnitude to be applied on this region + real(kind=realType) :: thrust + real(kind=realType) :: swirlFact + real(kind=realType) :: mDistribParam + real(kind=realType) :: nDistribParam + real(kind=realType) :: distribPDfactor + real(kind=realType) :: innerZeroThrustRadius + real(kind=realType) :: spinnerRadius + real(kind=realType) :: rootDragFactor - ! magnitude of the total torque to be applied on this region - real(kind=realType) :: torque - ! vector that determines the direction of the applied torque + ! T is the total torque to be applied on this regoin + real(kind=realType) :: T real(kind=realType), dimension(3) :: axisVec + real(kind=realType), dimension(:, :), pointer :: thrustVec + real(kind=realType), dimension(:, :), pointer :: swirlVec ! total heat flux to be added on this regoin - real(kind=realType) :: heat + ! Shamsheer note: heat is a new variable in the latest mdolab ADflow + ! real(kind=realType) :: heat ! Volume is the total integrated volume of all cells (on all ! procs) included in this region real(kind=realType) :: volume - real(kind=realType) :: volLocal + ! Shamsheer note: volLocal is a new variable in the latest mdolab ADflow + ! real(kind=realType) :: volLocal + + real(kind=realType) :: totalThrustSum + real(kind=realType) :: totalSwirlSum integer(kind=intType), dimension(:), allocatable :: blkPtr From c2cd5cee116d6def6573619cee0b9256775eeed9 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Wed, 17 Apr 2024 18:53:13 -0400 Subject: [PATCH 04/49] Modify actuatorRegion.F90 for the propeller model --- src/solver/actuatorRegion.F90 | 198 +++++++++++++++++++++++++++++----- 1 file changed, 170 insertions(+), 28 deletions(-) diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index e372cceae..44d7562dd 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -6,29 +6,29 @@ module actuatorRegion implicit none contains + ! Shamsheer note: Commented out this subroutine + ! subroutine computeActuatorRegionVolume(nn, iRegion) + ! use blockPointers, only: nDom, vol + ! implicit none - subroutine computeActuatorRegionVolume(nn, iRegion) - use blockPointers, only: nDom, vol - implicit none - - ! Inputs - integer(kind=intType), intent(in) :: nn, iRegion + ! ! Inputs + ! integer(kind=intType), intent(in) :: nn, iRegion - ! Working - integer(kind=intType) :: iii - integer(kind=intType) :: i, j, k + ! ! Working + ! integer(kind=intType) :: iii + ! integer(kind=intType) :: i, j, k - ! Loop over the region for this block - do iii = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1, actuatorRegions(iRegion)%blkPtr(nn) - i = actuatorRegions(iRegion)%cellIDs(1, iii) - j = actuatorRegions(iRegion)%cellIDs(2, iii) - k = actuatorRegions(iRegion)%cellIDs(3, iii) + ! ! Loop over the region for this block + ! do iii = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1, actuatorRegions(iRegion)%blkPtr(nn) + ! i = actuatorRegions(iRegion)%cellIDs(1, iii) + ! j = actuatorRegions(iRegion)%cellIDs(2, iii) + ! k = actuatorRegions(iRegion)%cellIDs(3, iii) - ! Sum the volume of each cell within the region on this proc - actuatorRegions(iRegion)%volLocal = actuatorRegions(iRegion)%volLocal + vol(i, j, k) - end do + ! ! Sum the volume of each cell within the region on this proc + ! actuatorRegions(iRegion)%volLocal = actuatorRegions(iRegion)%volLocal + vol(i, j, k) + ! end do - end subroutine computeActuatorRegionVolume + ! end subroutine computeActuatorRegionVolume ! ---------------------------------------------------------------------- ! | @@ -37,8 +37,10 @@ end subroutine computeActuatorRegionVolume ! ---------------------------------------------------------------------- #ifndef USE_TAPENADE - subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & - thrust, torque, heat, relaxStart, relaxEnd, nPts, nConn) + subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & + thrust, torque, swirlFact, mDistribParam, nDistribParam, & + distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, rootDragFactor, relaxStart, relaxEnd, nPts, nConn) + ! Shamsheer note: Removed heat from this subroutine ! Add a user-supplied integration surface. use communication, only: myID, adflow_comm_world @@ -47,7 +49,7 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & use adtLocalSearch, only: minDistanceTreeSearchSinglePoint use ADTUtils, only: stack use ADTData - use blockPointers, only: x, il, jl, kl, nDom, iBlank, vol + use blockPointers, only: x, il, jl, kl, nDom, iBlank, vol, volRef use adjointVars, only: nCellsLocal use utils, only: setPointers, EChk implicit none @@ -57,25 +59,32 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & real(kind=realType), dimension(3, nPts), intent(in), target :: pts integer(kind=intType), dimension(4, nConn), intent(in), target :: conn real(kind=realType), intent(in), dimension(3) :: axis1, axis2 - character(len=*) :: famName - real(kind=realType) :: thrust, torque, heat, relaxStart, relaxEnd + character(len=*) :: famName, actType + real(kind=realType) :: thrust, torque, relaxStart, relaxEnd, swirlFact + ! real(kind=realType) :: heat + ! Shamsheer note: Removed heat from the above line + real(kind=realType) :: mDistribParam, nDistribParam + real(kind=realType) :: distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, rootDragFactor ! Working variables integer(kind=intType) :: i, j, k, nn, iDim, cellID, intInfo(3), sps, level, iii, ierr - real(kind=realType) :: dStar, frac, volLocal + real(kind=realType) :: dStar, frac, volLocal, dotP type(actuatorRegionType), pointer :: region - real(kind=realType), dimension(3) :: minX, maxX, v1, v2, v3, xCen, axisVec + real(kind=realType), dimension(3) :: minX, maxX, v1, v2, v3, xCen, axisVec, radVec type(adtType) :: ADT real(kind=realType) :: axisVecNorm real(kind=realType), dimension(:, :), allocatable :: norm integer(kind=intType), dimension(:), allocatable :: normCount integer(kind=intType), dimension(:, :), pointer :: tmp + real(kind=realType), dimension(:, :), pointer :: tmp2 + real(kind=realType), dimension(:), pointer :: tmp3 ! ADT Type required data integer(kind=intType), dimension(:), pointer :: frontLeaves, frontLeavesNew type(adtBBoxTargetType), dimension(:), pointer :: BB real(kind=realType) :: coor(4), uvw(5) real(kind=realType) :: dummy(3, 2) + real(kind=realType) :: rHat, fact, fact2, swirlFact2, FTang, Swtmp, thrustSum, Ftmp, swirlSum nActuatorRegions = nActuatorRegions + 1 if (nActuatorRegions > nActuatorRegionsMax) then @@ -86,10 +95,12 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & ! Save the input information region => actuatorRegions(nActuatorRegions) + region%actType = actType region%famName = famName region%famID = famID - region%torque = torque - region%heat = heat + region%T = torque + ! region%heat = heat + ! Shamsheer note: Removed heat from here region%relaxStart = relaxStart region%relaxEnd = relaxEnd ! We use the axis to define the direction of F. Since we are @@ -105,7 +116,8 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & axisVec = axisVec / axisVecNorm - region%force = axisVec * thrust + region%F = axisVec * thrust + region%thrust = thrust region%axisVec = axisVec allocate (region%blkPtr(0:nDom)) @@ -172,11 +184,25 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & ! Allocate sufficient space for the maximum possible number of cellIDs allocate (region%cellIDs(3, nCellsLocal(1))) + if (region%actType == 'simpleProp') then + ! Allocate sufficient space for the maximum possible number of cellIDs + allocate(region%cellTangentials(3, nCellsLocal(1))) + allocate(region%thrustVec(3, nCellsLocal(1))) + allocate(region%swirlVec(3, nCellsLocal(1))) + + ! Allocate sufficient space for the maximum possible number of cellIDs + allocate(region%cellRadii(nCellsLocal(1))) + region%cellRadii(:) = zero + end if + ! Now search for all the coordinate. Note that We have explictly ! set sps to 1 becuase it is only implemented for single grid. sps = 1 level = 1 + thrustSum = zero + swirlSum = zero + do nn = 1, nDom call setPointers(nn, level, sps) do k = 2, kl @@ -205,6 +231,72 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & ! to the list. region%nCellIDs = region%nCellIDs + 1 region%cellIDs(:, region%nCellIDs) = (/i, j, k/) + if (region%actType == 'simpleProp') then + ! Compute cross product for tangential vector and normize + v1 = xCen - axis2 + v2 = axisVec + + v3(1) = (v1(2)*v2(3) - v1(3)*v2(2)) + v3(2) = (v1(3)*v2(1) - v1(1)*v2(3)) + v3(3) = (v1(1)*v2(2) - v1(2)*v2(1)) + v3 = v3 / sqrt(v3(1)**2 + v3(2)**2 + v3(3)**2) + region%cellTangentials(:, region%nCellIDs) = v3 + + ! Compute the dot product and subtract to get radius + dotP = v1(1)*v2(2) + v1(2)*v2(2) + v1(3)*v2(3) + radVec = v1 - dotP * axisVec + region%cellRadii(region%nCellIDs) = & + sqrt(radVec(1)**2 + radVec(2)**2 + radVec(3)**2) + + ! Compute unscaled thrust and swirl forces + if (region%cellRadii(region%nCellIDs) < spinnerRadius) then + + Ftmp = zero + region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec + + Swtmp = zero + region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) + + else if (region%cellRadii(region%nCellIDs) < innerZeroThrustRadius) then + + rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & + / (propRadius - innerZeroThrustRadius)) + fact = rootDragFactor / propRadius + fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & + / (two * pi * region%cellRadii(region%nCellIDs)) + Ftmp = volRef(i, j, k) * fact * fact2 + + ! thrustSum = thrustSum + Ftmp + + region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec + + Swtmp = zero + region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) + + else + + rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & + / (propRadius - innerZeroThrustRadius)) + fact = one / propRadius + fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & + / (two * pi * region%cellRadii(region%nCellIDs)) + Ftmp = volRef(i, j, k) * fact * fact2 + + thrustSum = thrustSum + Ftmp + + region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec + + swirlFact2 = distribPDfactor / pi / region%cellRadii(region%nCellIDs) & + * propRadius * swirlFact + FTang = swirlFact2 * fact * fact2 + Swtmp = volRef(i, j, k) * FTang + + swirlSum = swirlSum + Swtmp + + region%swirlVec(:, region%nCellIDs) = Swtmp & + * region%cellTangentials(:, region%nCellIDs) + end if + end if end if end if end if @@ -225,6 +317,36 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & region%cellIDs = tmp(:, 1:region%nCellIDs) deallocate (tmp) + if (region%actType == 'simpleProp') then + ! Resize the cellTangentials to the correct size now that we know the + ! correct exact number. + tmp2 => region%cellTangentials + allocate(region%cellTangentials(3, region%nCellIDs)) + region%cellTangentials = tmp2(:, 1:region%nCellIDs) + deallocate(tmp2) + + ! Resize the thrustVec to the correct size now that we know the + ! correct exact number. + tmp2 => region%thrustVec + allocate(region%thrustVec(3, region%nCellIDs)) + region%thrustVec = tmp2(:, 1:region%nCellIDs) + deallocate(tmp2) + + ! Resize the swirlVec to the correct size now that we know the + ! correct exact number. + tmp2 => region%swirlVec + allocate(region%swirlVec(3, region%nCellIDs)) + region%swirlVec = tmp2(:, 1:region%nCellIDs) + deallocate(tmp2) + + ! Resize the cellRadii to the correct size now that we know the + ! correct exact number. + tmp3 => region%cellRadii + allocate(region%cellRadii(region%nCellIDs)) + region%cellRadii = tmp3(1:region%nCellIDs) + deallocate(tmp3) + end if + ! Now go back and generate the total volume of the the cells we've flagged volLocal = zero @@ -243,6 +365,26 @@ subroutine addActuatorRegion(pts, conn, axis1, axis2, famName, famID, & call mpi_allreduce(volLocal, region%volume, 1, adflow_real, & MPI_SUM, adflow_comm_world, ierr) call ECHK(ierr, __FILE__, __LINE__) + write (*,*) "Total vol of actuator region is", region%volume + + if (region%actType == 'simpleProp') then + write (*,*) "thrust sum is", thrustSum + call mpi_allreduce(thrustSum, region%totalThrustSum, 1, adflow_real, & + MPI_SUM, adflow_comm_world, ierr) + call ECHK(ierr, __FILE__, __LINE__) + write (*,*) "Total thrust magnitude (mpi sum) without scaling factor is", region%totalThrustSum + + write (*,*) "swirl sum is", swirlSum + call mpi_allreduce(swirlSum, region%totalSwirlSum, 1, adflow_real, & + MPI_SUM, adflow_comm_world, ierr) + call ECHK(ierr, __FILE__, __LINE__) + write (*,*) "Total swirl magnitude (mpi sum) without scaling factor is", region%totalSwirlSum + + region%thrustVec = region%thrustVec / region%totalThrustSum + region%swirlVec = region%swirlVec / region%totalThrustSum + + deallocate(region%cellTangentials) + end if ! Final memory cleanup deallocate (stack, norm, frontLeaves, frontLeavesNew, BB) From 5d43602f90db2471a7122bd540b9cbea5ae28f93 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Thu, 18 Apr 2024 20:17:53 -0400 Subject: [PATCH 05/49] Modify residuals.F90 for the propeller model --- src/solver/residuals.F90 | 57 +++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/src/solver/residuals.F90 b/src/solver/residuals.F90 index 44d8a39a6..d0b9dd5ac 100644 --- a/src/solver/residuals.F90 +++ b/src/solver/residuals.F90 @@ -352,7 +352,9 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) use constants use actuatorRegionData use blockPointers, only: vol, dw, w - use flowVarRefState, only: pRef, uRef, LRef + use flowVarRefState, only: pRef, uRef + ! Shamsheer note: Commenting out heat term for now. + ! use LRef use communication use iteration, only: ordersConverged implicit none @@ -364,7 +366,9 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) ! Working integer(kind=intType) :: i, j, k, ii, iStart, iEnd - real(kind=realType) :: Ftmp(3), Vx, Vy, Vz, F_fact(3), Q_fact, Qtmp, reDim, factor, oStart, oEnd + real(kind=realType) :: Ftmp(3), Vx, Vy, Vz, F_fact(3), reDim, factor, oStart, oEnd + ! Shamsheer note: Commenting out heat term for now. + ! real(kind=realType) :: Q_fact, Qtmp reDim = pRef * uRef @@ -381,16 +385,22 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) factor = (ordersConverged - oStart) / (oEnd - oStart) end if + ! If using the uniform force distribution + if (actuatorRegions(iRegion)%actType == 'uniform') then ! Compute the constant force factor - F_fact = factor * actuatorRegions(iRegion)%force / actuatorRegions(iRegion)%volume / pRef + F_fact = factor * actuatorRegions(iRegion)%F / actuatorRegions(iRegion)%volume / pRef + end if ! Heat factor. This is heat added per unit volume per unit time - Q_fact = factor * actuatorRegions(iRegion)%heat / actuatorRegions(iRegion)%volume / (pRef * uRef * LRef * LRef) + ! Shamsheer note: Commenting out heat term for now. + ! Q_fact = factor * actuatorRegions(iRegion)%heat / actuatorRegions(iRegion)%volume / (pRef * uRef * LRef * LRef) ! Loop over the ranges for this block iStart = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1 iEnd = actuatorRegions(iRegion)%blkPtr(nn) + ! If using the uniform force distribution + if (actuatorRegions(iRegion)%actType == 'uniform') then !$AD II-LOOP do ii = iStart, iEnd @@ -407,20 +417,55 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) Vz = w(i, j, k, iVz) ! this gets the heat addition rate - QTmp = vol(i, j, k) * Q_fact + ! Shamsheer note: Commenting out heat term for now. + ! QTmp = vol(i, j, k) * Q_fact if (res) then ! Momentum residuals dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp ! energy residuals + ! Shamsheer note: Commenting out heat term for now. dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp + Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz + ! - Qtmp else ! Add in the local power contribution: pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim end if end do + end if + + ! If using the simple propeller force distribution + if (actuatorRegions(iRegion)%actType == 'simpleProp') then + !$AD II-LOOP + do ii=iStart, iEnd + + ! Extract the cell ID. + i = actuatorRegions(iRegion)%cellIDs(1, ii) + j = actuatorRegions(iRegion)%cellIDs(2, ii) + k = actuatorRegions(iRegion)%cellIDs(3, ii) + + Ftmp = factor * actuatorRegions(iRegion)%thrustVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef + Ftmp = Ftmp + factor * actuatorRegions(iRegion)%swirlVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef + + Vx = w(i, j, k, iVx) + Vy = w(i, j, k, iVy) + Vz = w(i, j, k, iVz) + + if (res) then + ! Momentum residuals + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp + + ! energy residuals + dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & + Ftmp(1)*Vx - Ftmp(2)*Vy - Ftmp(3)*Vz + else + ! Add in the local power contribution: + pLocal = pLocal + (Vx*Ftmp(1) + Vy*Ftmp(2) + Vz*Ftmp(3))*reDim + end if + end do + end if end subroutine sourceTerms_block From ad86edc2f46fb6bfc8f44f5d2b96e4822225f949 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Wed, 24 Apr 2024 15:12:04 -0400 Subject: [PATCH 06/49] Bring back heat and VolLocal in actuator code --- adflow/pyADflow.py | 16 ++++------- src/f2py/adflow.pyf | 5 ++-- src/modules/actuatorRegionData.F90 | 11 ++++---- src/solver/actuatorRegion.F90 | 45 +++++++++++++----------------- src/solver/residuals.F90 | 18 ++++-------- 5 files changed, 38 insertions(+), 57 deletions(-) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 92f3baeb7..50e9cba96 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -883,7 +883,7 @@ def addActuatorRegion( familyName, thrust=0.0, torque=0.0, - # heat=0.0, + heat=0.0, swirlFact=0.0, mDistribParam=1.0, nDistribParam=0.5, @@ -985,14 +985,12 @@ def addActuatorRegion( applied inside the innerZeroThrustRadius for the propeller model. See below for a description of innerZeroThrustRadius.) - torque : scalar + torque : scalar, float The total amount of torque to apply to the region, about the specified axis. This is only for the uniform actuator zone. - # ----- Shamsheer note: This is new in the mdolab ADflow. If needed, incorporate later. ------- - # heat : scalar, float - # The total amount of head added in the actuator zone with source terms - # --------------------------------------------------------------------------------------------- + heat : scalar, float + The total amount of head added in the actuator zone with source terms relaxStart : scalar, float The start of the relaxation in terms of @@ -1091,10 +1089,8 @@ def addActuatorRegion( # Now continue to fortran were we setup the actual region. self.adflow.actuatorregion.addactuatorregion( - pts.T, conn.T, actType, axis1, axis2, familyName, famID, thrust, torque, - # heat - swirlFact, - mDistribParam, nDistribParam, distribPDfactor, innerZeroThrustRadius, + pts.T, conn.T, actType, axis1, axis2, familyName, famID, thrust, torque, heat, + swirlFact, mDistribParam, nDistribParam, distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, rootDragFactor, relaxStart, relaxEnd) def writeActuatorRegions(self, fileName, outputDir=None): diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index 2b2870df0..0cdcf5c77 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -677,7 +677,7 @@ python module libadflow end module usersurfaceintegrations module actuatorregion ! in :test:actuatorDiskRegion.F90 - subroutine addactuatorregion(pts,conn,acttype,axis1,axis2,famname,famid,thrust,torque,swirlfact,mdistribparam,ndistribparam,distribpdfactor,innerzerothrustradius,propradius,spinnerradius,rootdragfactor,relaxstart,relaxend,npts,nconn) ! in :test:actuatorDiskRegion.F90:actuatorregion + subroutine addactuatorregion(pts,conn,acttype,axis1,axis2,famname,famid,thrust,torque,heat,swirlfact,mdistribparam,ndistribparam,distribpdfactor,innerzerothrustradius,propradius,spinnerradius,rootdragfactor,relaxstart,relaxend,npts,nconn) ! in :test:actuatorDiskRegion.F90:actuatorregion real(kind=realtype) dimension(3,npts),intent(in) :: pts integer(kind=inttype) dimension(4,nconn),intent(in) :: conn character*(*) :: acttype @@ -687,8 +687,7 @@ python module libadflow integer(kind=inttype) intent(in) :: famid real(kind=realtype) :: thrust real(kind=realtype) :: torque - !# Shamsheer commented out heat and removed from the subroutine line above. - !# real(kind=realtype) :: heat + real(kind=realtype) :: heat real(kind=realtype) :: swirlfact real(kind=realtype) :: mdistribparam real(kind=realtype) :: ndistribparam diff --git a/src/modules/actuatorRegionData.F90 b/src/modules/actuatorRegionData.F90 index 539233776..5ff216c46 100644 --- a/src/modules/actuatorRegionData.F90 +++ b/src/modules/actuatorRegionData.F90 @@ -16,7 +16,7 @@ module actuatorRegionData ! The total number of cells included this proc has integer(kind=intType) :: nCellIDs - ! F is the total Force to be applied on this region + ! F is the force vector to be applied on this region real(kind=realType) :: F(3) ! thrust is the total thrust magnitude to be applied on this region @@ -29,21 +29,20 @@ module actuatorRegionData real(kind=realType) :: spinnerRadius real(kind=realType) :: rootDragFactor - ! T is the total torque to be applied on this regoin + ! T is the total torque to be applied on this region real(kind=realType) :: T + ! vector that determines the direction of the applied torque and force real(kind=realType), dimension(3) :: axisVec real(kind=realType), dimension(:, :), pointer :: thrustVec real(kind=realType), dimension(:, :), pointer :: swirlVec ! total heat flux to be added on this regoin - ! Shamsheer note: heat is a new variable in the latest mdolab ADflow - ! real(kind=realType) :: heat + real(kind=realType) :: heat ! Volume is the total integrated volume of all cells (on all ! procs) included in this region real(kind=realType) :: volume - ! Shamsheer note: volLocal is a new variable in the latest mdolab ADflow - ! real(kind=realType) :: volLocal + real(kind=realType) :: volLocal real(kind=realType) :: totalThrustSum real(kind=realType) :: totalSwirlSum diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 44d7562dd..478bc84b2 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -6,29 +6,28 @@ module actuatorRegion implicit none contains - ! Shamsheer note: Commented out this subroutine - ! subroutine computeActuatorRegionVolume(nn, iRegion) - ! use blockPointers, only: nDom, vol - ! implicit none + subroutine computeActuatorRegionVolume(nn, iRegion) + use blockPointers, only: nDom, vol + implicit none - ! ! Inputs - ! integer(kind=intType), intent(in) :: nn, iRegion + ! Inputs + integer(kind=intType), intent(in) :: nn, iRegion - ! ! Working - ! integer(kind=intType) :: iii - ! integer(kind=intType) :: i, j, k + ! Working + integer(kind=intType) :: iii + integer(kind=intType) :: i, j, k - ! ! Loop over the region for this block - ! do iii = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1, actuatorRegions(iRegion)%blkPtr(nn) - ! i = actuatorRegions(iRegion)%cellIDs(1, iii) - ! j = actuatorRegions(iRegion)%cellIDs(2, iii) - ! k = actuatorRegions(iRegion)%cellIDs(3, iii) + ! Loop over the region for this block + do iii = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1, actuatorRegions(iRegion)%blkPtr(nn) + i = actuatorRegions(iRegion)%cellIDs(1, iii) + j = actuatorRegions(iRegion)%cellIDs(2, iii) + k = actuatorRegions(iRegion)%cellIDs(3, iii) - ! ! Sum the volume of each cell within the region on this proc - ! actuatorRegions(iRegion)%volLocal = actuatorRegions(iRegion)%volLocal + vol(i, j, k) - ! end do + ! Sum the volume of each cell within the region on this proc + actuatorRegions(iRegion)%volLocal = actuatorRegions(iRegion)%volLocal + vol(i, j, k) + end do - ! end subroutine computeActuatorRegionVolume + end subroutine computeActuatorRegionVolume ! ---------------------------------------------------------------------- ! | @@ -38,9 +37,8 @@ module actuatorRegion #ifndef USE_TAPENADE subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & - thrust, torque, swirlFact, mDistribParam, nDistribParam, & + thrust, torque, heat, swirlFact, mDistribParam, nDistribParam, & distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, rootDragFactor, relaxStart, relaxEnd, nPts, nConn) - ! Shamsheer note: Removed heat from this subroutine ! Add a user-supplied integration surface. use communication, only: myID, adflow_comm_world @@ -60,9 +58,7 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & integer(kind=intType), dimension(4, nConn), intent(in), target :: conn real(kind=realType), intent(in), dimension(3) :: axis1, axis2 character(len=*) :: famName, actType - real(kind=realType) :: thrust, torque, relaxStart, relaxEnd, swirlFact - ! real(kind=realType) :: heat - ! Shamsheer note: Removed heat from the above line + real(kind=realType) :: thrust, torque, heat, relaxStart, relaxEnd, swirlFact real(kind=realType) :: mDistribParam, nDistribParam real(kind=realType) :: distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, rootDragFactor @@ -99,8 +95,7 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & region%famName = famName region%famID = famID region%T = torque - ! region%heat = heat - ! Shamsheer note: Removed heat from here + region%heat = heat region%relaxStart = relaxStart region%relaxEnd = relaxEnd ! We use the axis to define the direction of F. Since we are diff --git a/src/solver/residuals.F90 b/src/solver/residuals.F90 index d0b9dd5ac..6376c3fef 100644 --- a/src/solver/residuals.F90 +++ b/src/solver/residuals.F90 @@ -352,9 +352,7 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) use constants use actuatorRegionData use blockPointers, only: vol, dw, w - use flowVarRefState, only: pRef, uRef - ! Shamsheer note: Commenting out heat term for now. - ! use LRef + use flowVarRefState, only: pRef, uRef, LRef use communication use iteration, only: ordersConverged implicit none @@ -366,9 +364,7 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) ! Working integer(kind=intType) :: i, j, k, ii, iStart, iEnd - real(kind=realType) :: Ftmp(3), Vx, Vy, Vz, F_fact(3), reDim, factor, oStart, oEnd - ! Shamsheer note: Commenting out heat term for now. - ! real(kind=realType) :: Q_fact, Qtmp + real(kind=realType) :: Ftmp(3), Vx, Vy, Vz, F_fact(3), Q_fact, Qtmp, reDim, factor, oStart, oEnd reDim = pRef * uRef @@ -392,8 +388,7 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) end if ! Heat factor. This is heat added per unit volume per unit time - ! Shamsheer note: Commenting out heat term for now. - ! Q_fact = factor * actuatorRegions(iRegion)%heat / actuatorRegions(iRegion)%volume / (pRef * uRef * LRef * LRef) + Q_fact = factor * actuatorRegions(iRegion)%heat / actuatorRegions(iRegion)%volume / (pRef * uRef * LRef * LRef) ! Loop over the ranges for this block iStart = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1 @@ -417,18 +412,15 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) Vz = w(i, j, k, iVz) ! this gets the heat addition rate - ! Shamsheer note: Commenting out heat term for now. - ! QTmp = vol(i, j, k) * Q_fact + QTmp = vol(i, j, k) * Q_fact if (res) then ! Momentum residuals dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp ! energy residuals - ! Shamsheer note: Commenting out heat term for now. dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - ! - Qtmp + Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp else ! Add in the local power contribution: pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim From d8e23679bb7e14f2ead07fc5cc67e4ac360c55d3 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Wed, 24 Apr 2024 15:58:46 -0400 Subject: [PATCH 07/49] Modify Makefile_tapenade for the propeller model --- src/adjoint/Makefile_tapenade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adjoint/Makefile_tapenade b/src/adjoint/Makefile_tapenade index d0077a2ea..10472bc30 100644 --- a/src/adjoint/Makefile_tapenade +++ b/src/adjoint/Makefile_tapenade @@ -183,8 +183,8 @@ sa%saViscous(w, vol, si, sj, sk, rlv, scratch) > \ sa%saResScale(scratch, dw) > \ (dw) \ \ -residuals%sourceTerms_block(w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%heat, actuatorRegions%volume) > \ - (w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%heat, actuatorRegions%volume) \ +residuals%sourceTerms_block(w, pref, uref, plocal, dw, vol, actuatorRegions%F, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) > \ + (w, pref, uref, plocal, dw, vol, actuatorRegions%F, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) \ \ residuals%initres_block(dw, fw, flowDoms%w, flowDoms%vol, dscalar, dvector) > \ (dw, fw, flowDoms%w, flowDoms%vol, dscalar, dvector) \ From 0dc4ccf6eb9be9e8487a742e18c70f51d3219ae2 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Thu, 25 Apr 2024 01:01:46 -0400 Subject: [PATCH 08/49] Modify residuals_d.f90 for the propeller model --- src/adjoint/outputForward/residuals_d.f90 | 102 ++++++++++++++++++++-- 1 file changed, 93 insertions(+), 9 deletions(-) diff --git a/src/adjoint/outputForward/residuals_d.f90 b/src/adjoint/outputForward/residuals_d.f90 index 8e12ed2e6..944e6d7c5 100644 --- a/src/adjoint/outputForward/residuals_d.f90 +++ b/src/adjoint/outputForward/residuals_d.f90 @@ -340,10 +340,10 @@ end subroutine residual_block ! differentiation of sourceterms_block in forward (tangent) mode (with options i4 dr8 r8): ! variations of useful results: *dw plocal -! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.heat actuatorregions.volume plocal +! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.f +! actuatorregions.thrust actuatorregions.heat actuatorregions.volume plocal ! rw status of diff variables: uref:in pref:in *w:in *dw:in-out -! *vol:in actuatorregions.force:in actuatorregions.heat:in +! *vol:in actuatorregions.f:in actuatorregions.thrust:in actuatorregions.heat:in ! actuatorregions.volume:in plocal:in-out ! plus diff mem management of: w:in dw:in vol:in subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) @@ -385,12 +385,14 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor temp = actuatorregions(iregion)%volume*pref - f_factd = factor*(actuatorregionsd(iregion)%force-actuatorregions(& -& iregion)%force*(pref*actuatorregionsd(iregion)%volume+& + f_factd = factor*(actuatorregionsd(iregion)%f-actuatorregions(& +& iregion)%f*(pref*actuatorregionsd(iregion)%volume+& & actuatorregions(iregion)%volume*prefd)/temp)/temp - f_fact = factor*(actuatorregions(iregion)%force/temp) + f_fact = factor*(actuatorregions(iregion)%f/temp) ! heat factor. this is heat added per unit volume per unit time temp = lref*lref*actuatorregions(iregion)%volume temp0 = temp*pref*uref @@ -399,9 +401,15 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) & lref**2*actuatorregionsd(iregion)%volume+temp*(uref*prefd+pref*& & urefd)))/temp0 q_fact = factor*temp1 + else + f_factd = 0.0_8 + q_factd = 0.0_8 + end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) @@ -437,8 +445,52 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) plocal = plocal + temp1*redim end if end do + end if +! if using the simple propeller force distribution + if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then + do ii=istart,iend +! extract the cell id. + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) + ftmpd = (factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& actuatorregionsd(iregion)%thrust*pref-factor*actuatorregions(& +& iregion)%thrustvec(:, ii)*actuatorregions(iregion)%thrust*& +& prefd)/pref**2 + ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + ftmpd = ftmpd + (factor*actuatorregions(iregion)%swirlvec(:, ii)& +& *actuatorregionsd(iregion)%thrust*pref-factor*actuatorregions(& +& iregion)%swirlvec(:, ii)*actuatorregions(iregion)%thrust*prefd& +& )/pref**2 + ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + vxd = wd(i, j, k, ivx) + vx = w(i, j, k, ivx) + vyd = wd(i, j, k, ivy) + vy = w(i, j, k, ivy) + vzd = wd(i, j, k, ivz) + vz = w(i, j, k, ivz) + if (res) then +! momentum residuals + dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp +! energy residuals + dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - ftmpd(1)*vx - ftmp& +& (1)*vxd - ftmpd(2)*vy - ftmp(2)*vyd - ftmpd(3)*vz - ftmp(3)*& +& vzd + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz + else +! add in the local power contribution: + plocald = plocald + (vxd*ftmp(1)+vx*ftmpd(1)+vyd*ftmp(2)+vy*& +& ftmpd(2)+vzd*ftmp(3)+vz*ftmpd(3))*redim + (vx*ftmp(1)+vy*& +& ftmp(2)+vz*ftmp(3))*redimd + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do + end if end subroutine sourceterms_block_d - subroutine sourceterms_block(nn, res, iregion, plocal) ! apply the source terms for the given block. assume that the ! block pointers are already set. @@ -471,16 +523,21 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if +!$ad ii-loop +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& + f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& & iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) + end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -!$ad ii-loop +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) @@ -504,6 +561,33 @@ subroutine sourceterms_block(nn, res, iregion, plocal) plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim end if end do + end if +! if using the simple propeller force distribution + if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then + do ii=istart,iend +! extract the cell id. + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) + ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) + if (res) then +! momentum residuals + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp +! energy residuals + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz + else +! add in the local power contribution: + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do + end if end subroutine sourceterms_block ! differentiation of initres_block in forward (tangent) mode (with options i4 dr8 r8): From 621dd3f46e55733ce110a1bb580ffbc96faec663 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Thu, 25 Apr 2024 18:20:40 -0400 Subject: [PATCH 09/49] Modify adjointUtils.f90 for propeller model --- src/adjoint/adjointUtils.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/adjoint/adjointUtils.F90 b/src/adjoint/adjointUtils.F90 index bc46bc30c..6adccfa2d 100644 --- a/src/adjoint/adjointUtils.F90 +++ b/src/adjoint/adjointUtils.F90 @@ -1074,8 +1074,9 @@ subroutine zeroADSeeds(nn, level, sps) ! And the reverse seeds in the actuator zones do i = 1, nActuatorRegions - actuatorRegionsd(i)%force = zero - actuatorRegionsd(i)%torque = zero + actuatorRegionsd(i)%F = zero + actuatorRegionsd(i)%T = zero + actuatorRegionsd(i)%thrust = zero actuatorRegionsd(i)%heat = zero actuatorRegionsd(i)%volume = zero end do From e58050646ccb50d60c9d58791742e54b429e7e62 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Fri, 26 Apr 2024 16:02:39 -0400 Subject: [PATCH 10/49] Modify residuals_b.f90 for propeller model --- src/adjoint/outputReverse/residuals_b.f90 | 125 ++++++++++++++++++++-- 1 file changed, 114 insertions(+), 11 deletions(-) diff --git a/src/adjoint/outputReverse/residuals_b.f90 b/src/adjoint/outputReverse/residuals_b.f90 index b16d723d8..e12ec369c 100644 --- a/src/adjoint/outputReverse/residuals_b.f90 +++ b/src/adjoint/outputReverse/residuals_b.f90 @@ -335,12 +335,12 @@ subroutine residual_block() end subroutine residual_block ! differentiation of sourceterms_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): -! gradient of useful results: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.heat actuatorregions.volume plocal -! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.heat actuatorregions.volume plocal +! gradient of useful results: uref pref *w *dw *vol actuatorregions.f +! actuatorregions.thrust actuatorregions.heat actuatorregions.volume plocal +! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.f +! actuatorregions.thrust actuatorregions.heat actuatorregions.volume plocal ! rw status of diff variables: uref:incr pref:incr *w:incr *dw:in-out -! *vol:incr actuatorregions.force:incr actuatorregions.heat:incr +! *vol:incr actuatorregions.f:incr actuatorregions.thrust actuatorregions.heat:incr ! actuatorregions.volume:incr plocal:in-out ! plus diff mem management of: w:in dw:in vol:in subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) @@ -365,6 +365,7 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) real(kind=realtype) :: ftmpd(3), vxd, vyd, vzd, f_factd(3), q_factd& & , qtmpd, redimd real(kind=realtype), dimension(3) :: tempd + real(kind=realtype) :: tempd3 real(kind=realtype) :: temp real(kind=realtype) :: tempd0 real(kind=realtype) :: temp0 @@ -388,18 +389,83 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& + f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& & iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) + call pushcontrol1b(0) + else + call pushcontrol1b(1) + end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then + call pushcontrol1b(0) + else + call pushcontrol1b(1) + end if q_factd = 0.0_8 redimd = 0.0_8 f_factd = 0.0_8 +! if using the simple propeller force distribution + if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then + redimd = 0.0_8 + do ii=istart,iend +! extract the cell id. + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) + ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) + if (res) then + ftmpd = 0.0_8 + ftmpd(1) = ftmpd(1) - vx*dwd(i, j, k, irhoe) + vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) + ftmpd(2) = ftmpd(2) - vy*dwd(i, j, k, irhoe) + vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) + ftmpd(3) = ftmpd(3) - vz*dwd(i, j, k, irhoe) + vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) + ftmpd = ftmpd - dwd(i, j, k, imx:imz) + else + ftmpd = 0.0_8 + tempd3 = redim*plocald + vxd = ftmp(1)*tempd3 + ftmpd(1) = ftmpd(1) + vx*tempd3 + vyd = ftmp(2)*tempd3 + ftmpd(2) = ftmpd(2) + vy*tempd3 + vzd = ftmp(3)*tempd3 + ftmpd(3) = ftmpd(3) + vz*tempd3 + redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald + end if + tempd2 = sum(factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& ftmpd)/pref + wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd + wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd + wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd + tempd1 = sum(factor*actuatorregions(iregion)%swirlvec(:, ii)*& +& ftmpd)/pref + actuatorregionsd(iregion)%thrust = actuatorregionsd(iregion)%& +& thrust + tempd2 + tempd1 + prefd = prefd - actuatorregions(iregion)%thrust*tempd2/pref - & +& actuatorregions(iregion)%thrust*tempd1/pref + end do + else + redimd = 0.0_8 + end if + call popcontrol1b(branch) + if (branch .eq. 0) then + f_factd = 0.0_8 !$bwd-of ii-loop do ii=istart,iend ! extract the cell id. @@ -441,8 +507,13 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd f_factd = f_factd + vol(i, j, k)*ftmpd end do + else + factd = 0.0_8 + end if + call popcontrol1b(branch) + if (branch .eq. 0) then tempd = factor*f_factd/(actuatorregions(iregion)%volume*pref) - tempd0 = -(sum(actuatorregions(iregion)%force*tempd)/(& + tempd0 = -(sum(actuatorregions(iregion)%f*tempd)/(& & actuatorregions(iregion)%volume*pref)) temp = lref*lref*actuatorregions(iregion)%volume temp0 = temp*pref*uref @@ -455,9 +526,9 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) prefd = prefd + uref*temp*tempd2 + actuatorregions(iregion)%volume*& & tempd0 urefd = urefd + pref*temp*tempd2 - actuatorregionsd(iregion)%force = actuatorregionsd(iregion)%force + & + actuatorregionsd(iregion)%f = actuatorregionsd(iregion)%f + & & tempd - call popcontrol1b(branch) + endif prefd = prefd + uref*redimd urefd = urefd + pref*redimd end subroutine sourceterms_block_b @@ -494,16 +565,21 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& + f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& & iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) + end if +!$ad ii-loop ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -!$ad ii-loop +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) @@ -527,6 +603,33 @@ subroutine sourceterms_block(nn, res, iregion, plocal) plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim end if end do + end if +! if using the simple propeller force distribution + if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then + do ii=istart,iend +! extract the cell id. + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) + ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) + if (res) then +! momentum residuals + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp +! energy residuals + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz + else +! add in the local power contribution: + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do + end if end subroutine sourceterms_block ! differentiation of initres_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): From 6cae1831cee642c540aa71c3a19f26a7990ab350 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Sat, 27 Apr 2024 00:35:01 -0400 Subject: [PATCH 11/49] Modify residuals_fast_b.f90 for the propeller model --- .../outputReverseFast/residuals_fast_b.f90 | 81 ++++++++++++++++--- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/src/adjoint/outputReverseFast/residuals_fast_b.f90 b/src/adjoint/outputReverseFast/residuals_fast_b.f90 index edf78f8d1..537971c4b 100644 --- a/src/adjoint/outputReverseFast/residuals_fast_b.f90 +++ b/src/adjoint/outputReverseFast/residuals_fast_b.f90 @@ -362,29 +362,61 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: if (ordersconverged .lt. actuatorregions(iregion)%relaxstart) then -myIntPtr = myIntPtr + 1 - myIntStack(myIntPtr) = 0 factor = zero else if (ordersconverged .gt. actuatorregions(iregion)%relaxend) & & then -myIntPtr = myIntPtr + 1 - myIntStack(myIntPtr) = 1 factor = one else -myIntPtr = myIntPtr + 1 - myIntStack(myIntPtr) = 1 ! in between ostart = actuatorregions(iregion)%relaxstart oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') fact then ! compute the constant force factor f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& & iregion)%volume/pref -! heat factor. this is heat added per unit volume per unit time + end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then +myIntPtr = myIntPtr + 1 + myIntStack(myIntPtr) = 0 + else +myIntPtr = myIntPtr + 1 + myIntStack(myIntPtr) = 1 + end if +! if using the simple propeller force distribution + if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then + do ii=istart,iend +! extract the cell id. + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) + ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + if (res) then + vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) + vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) + vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) + else + vxd = 0.0_8 + vyd = 0.0_8 + vzd = 0.0_8 + end if + wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd + wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd + wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd + end do + end if +branch = myIntStack(myIntPtr) + myIntPtr = myIntPtr - 1 + if (branch .eq. 0) then !$bwd-of ii-loop do ii=istart,iend ! extract the cell id. @@ -407,8 +439,7 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd end do -branch = myIntStack(myIntPtr) - myIntPtr = myIntPtr - 1 + end if end subroutine sourceterms_block_fast_b subroutine sourceterms_block(nn, res, iregion, plocal) @@ -443,16 +474,21 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& & iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) + end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) !$ad ii-loop +! if using the uniform force distribution + if (actuatorregions(iregion)%acttype .eq. 'uniform') then do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) @@ -476,6 +512,33 @@ subroutine sourceterms_block(nn, res, iregion, plocal) plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim end if end do + end if +! if using the simple propeller force distribution + if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then + do ii=istart,iend +! extract the cell id. + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) + ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& +& actuatorregions(iregion)%thrust/pref + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) + if (res) then +! momentum residuals + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp +! energy residuals + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz + else +! add in the local power contribution: + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do + end if end subroutine sourceterms_block ! differentiation of initres_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): From d6a5c76ec4a88abf252afa4766dc93a636543280 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Wed, 1 May 2024 16:32:00 -0400 Subject: [PATCH 12/49] Change remaining %force and %torque to %f and %t --- src/adjoint/adjointDebug.F90 | 4 ++-- .../outputReverseFast/residuals_fast_b.f90 | 4 ++-- src/bcdata/BCData.F90 | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/adjoint/adjointDebug.F90 b/src/adjoint/adjointDebug.F90 index 24119b4d8..0f7bf2d9e 100644 --- a/src/adjoint/adjointDebug.F90 +++ b/src/adjoint/adjointDebug.F90 @@ -558,8 +558,8 @@ subroutine printADSeeds(nn, level, sps) ! And the reverse seeds in the actuator zones do i = 1, nActuatorRegions - write (*, *) 'actuatorRegionsd(i)%Force ', actuatorRegionsd(i)%force - write (*, *) 'actuatorRegionsd(i)%Torque ', actuatorRegionsd(i)%torque + write (*, *) 'actuatorRegionsd(i)%F ', actuatorRegionsd(i)%f + write (*, *) 'actuatorRegionsd(i)%T ', actuatorRegionsd(i)%t end do end subroutine printADSeeds diff --git a/src/adjoint/outputReverseFast/residuals_fast_b.f90 b/src/adjoint/outputReverseFast/residuals_fast_b.f90 index 537971c4b..abb62ecb6 100644 --- a/src/adjoint/outputReverseFast/residuals_fast_b.f90 +++ b/src/adjoint/outputReverseFast/residuals_fast_b.f90 @@ -375,7 +375,7 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') fact then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& + f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& & iregion)%volume/pref end if ! loop over the ranges for this block @@ -477,7 +477,7 @@ subroutine sourceterms_block(nn, res, iregion, plocal) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& + f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& & iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& diff --git a/src/bcdata/BCData.F90 b/src/bcdata/BCData.F90 index f8ebb836d..6780774c6 100644 --- a/src/bcdata/BCData.F90 +++ b/src/bcdata/BCData.F90 @@ -1485,10 +1485,10 @@ subroutine setBCData(bcDataNamesIn, bcDataIn, famLists, sps, & varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) if (trim(varName) == "Thrust") then - actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & + actuatorRegions(iRegion)%f = actuatorRegions(iRegion)%axisVec * & bcDataIn(iVar) else if (trim(varName) == "Torque") then - actuatorRegions(iRegion)%torque = bcDataIn(iVar) + actuatorRegions(iRegion)%t = bcDataIn(iVar) else if (trim(varName) == "Heat") then actuatorRegions(iRegion)%heat = bcDataIn(iVar) end if @@ -1583,13 +1583,13 @@ subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) if (trim(varName) == "Thrust") then - actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & + actuatorRegions(iRegion)%f = actuatorRegions(iRegion)%axisVec * & bcDataIn(iVar) - actuatorRegionsd(iRegion)%force = actuatorRegions(iRegion)%axisVec * & + actuatorRegionsd(iRegion)%f = actuatorRegions(iRegion)%axisVec * & bcDataInd(iVar) else if (trim(varName) == "Torque") then - actuatorRegions(iRegion)%torque = bcDataIn(iVar) - actuatorRegionsd(iRegion)%torque = bcDataInd(iVar) + actuatorRegions(iRegion)%t = bcDataIn(iVar) + actuatorRegionsd(iRegion)%t = bcDataInd(iVar) else if (trim(varName) == "Heat") then actuatorRegions(iRegion)%heat = bcDataIn(iVar) actuatorRegionsd(iRegion)%heat = bcDataInd(iVar) @@ -1689,9 +1689,9 @@ subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & if (trim(varName) == "Thrust") then bcDataInd(ivar) = & - sum(actuatorRegions(iRegion)%axisVec * actuatorRegionsd(iRegion)%force) + sum(actuatorRegions(iRegion)%axisVec * actuatorRegionsd(iRegion)%f) else if (trim(varName) == "Torque") then - bcDataInd(ivar) = actuatorRegionsd(iRegion)%torque + bcDataInd(ivar) = actuatorRegionsd(iRegion)%t else if (trim(varName) == "Heat") then bcDataInd(ivar) = actuatorRegionsd(iRegion)%heat end if From d0893037baf83df9b2517d66bad14aff3d12b344 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Wed, 1 May 2024 18:52:20 -0400 Subject: [PATCH 13/49] Fix errors related to `fact` in merged adjoint code --- src/adjoint/outputReverse/residuals_b.f90 | 4 +++- src/adjoint/outputReverseFast/residuals_fast_b.f90 | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/adjoint/outputReverse/residuals_b.f90 b/src/adjoint/outputReverse/residuals_b.f90 index e12ec369c..c9e64ded5 100644 --- a/src/adjoint/outputReverse/residuals_b.f90 +++ b/src/adjoint/outputReverse/residuals_b.f90 @@ -466,6 +466,7 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) call popcontrol1b(branch) if (branch .eq. 0) then f_factd = 0.0_8 + q_factd = 0.0_8 !$bwd-of ii-loop do ii=istart,iend ! extract the cell id. @@ -508,7 +509,8 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) f_factd = f_factd + vol(i, j, k)*ftmpd end do else - factd = 0.0_8 + f_factd = 0.0_8 + q_factd = 0.0_8 end if call popcontrol1b(branch) if (branch .eq. 0) then diff --git a/src/adjoint/outputReverseFast/residuals_fast_b.f90 b/src/adjoint/outputReverseFast/residuals_fast_b.f90 index abb62ecb6..59ec18ae0 100644 --- a/src/adjoint/outputReverseFast/residuals_fast_b.f90 +++ b/src/adjoint/outputReverseFast/residuals_fast_b.f90 @@ -373,7 +373,7 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) factor = (ordersconverged-ostart)/(oend-ostart) end if ! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') fact then + if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& & iregion)%volume/pref From d7dc861ea603fe72ea03e1b2e89cfbd7e2eaf272 Mon Sep 17 00:00:00 2001 From: "Shamsheer S. Chauhan" Date: Thu, 2 May 2024 00:56:49 -0400 Subject: [PATCH 14/49] Restrict lines to 132 char in actuatorRegion.F90 --- src/solver/actuatorRegion.F90 | 101 +++++++++++++++++----------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 478bc84b2..9c55dca54 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -38,7 +38,8 @@ end subroutine computeActuatorRegionVolume #ifndef USE_TAPENADE subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & thrust, torque, heat, swirlFact, mDistribParam, nDistribParam, & - distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, rootDragFactor, relaxStart, relaxEnd, nPts, nConn) + distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, & + rootDragFactor, relaxStart, relaxEnd, nPts, nConn) ! Add a user-supplied integration surface. use communication, only: myID, adflow_comm_world @@ -226,72 +227,72 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & ! to the list. region%nCellIDs = region%nCellIDs + 1 region%cellIDs(:, region%nCellIDs) = (/i, j, k/) - if (region%actType == 'simpleProp') then - ! Compute cross product for tangential vector and normize - v1 = xCen - axis2 - v2 = axisVec + if (region%actType == 'simpleProp') then + ! Compute cross product for tangential vector and normize + v1 = xCen - axis2 + v2 = axisVec - v3(1) = (v1(2)*v2(3) - v1(3)*v2(2)) - v3(2) = (v1(3)*v2(1) - v1(1)*v2(3)) - v3(3) = (v1(1)*v2(2) - v1(2)*v2(1)) - v3 = v3 / sqrt(v3(1)**2 + v3(2)**2 + v3(3)**2) - region%cellTangentials(:, region%nCellIDs) = v3 + v3(1) = (v1(2)*v2(3) - v1(3)*v2(2)) + v3(2) = (v1(3)*v2(1) - v1(1)*v2(3)) + v3(3) = (v1(1)*v2(2) - v1(2)*v2(1)) + v3 = v3 / sqrt(v3(1)**2 + v3(2)**2 + v3(3)**2) + region%cellTangentials(:, region%nCellIDs) = v3 - ! Compute the dot product and subtract to get radius - dotP = v1(1)*v2(2) + v1(2)*v2(2) + v1(3)*v2(3) - radVec = v1 - dotP * axisVec - region%cellRadii(region%nCellIDs) = & - sqrt(radVec(1)**2 + radVec(2)**2 + radVec(3)**2) + ! Compute the dot product and subtract to get radius + dotP = v1(1)*v2(2) + v1(2)*v2(2) + v1(3)*v2(3) + radVec = v1 - dotP * axisVec + region%cellRadii(region%nCellIDs) = & + sqrt(radVec(1)**2 + radVec(2)**2 + radVec(3)**2) - ! Compute unscaled thrust and swirl forces - if (region%cellRadii(region%nCellIDs) < spinnerRadius) then + ! Compute unscaled thrust and swirl forces + if (region%cellRadii(region%nCellIDs) < spinnerRadius) then - Ftmp = zero - region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec + Ftmp = zero + region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec - Swtmp = zero - region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) + Swtmp = zero + region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) - else if (region%cellRadii(region%nCellIDs) < innerZeroThrustRadius) then + else if (region%cellRadii(region%nCellIDs) < innerZeroThrustRadius) then - rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & - / (propRadius - innerZeroThrustRadius)) - fact = rootDragFactor / propRadius - fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & - / (two * pi * region%cellRadii(region%nCellIDs)) - Ftmp = volRef(i, j, k) * fact * fact2 + rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & + / (propRadius - innerZeroThrustRadius)) + fact = rootDragFactor / propRadius + fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & + / (two * pi * region%cellRadii(region%nCellIDs)) + Ftmp = volRef(i, j, k) * fact * fact2 - ! thrustSum = thrustSum + Ftmp + thrustSum = thrustSum + Ftmp - region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec + region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec - Swtmp = zero - region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) + Swtmp = zero + region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) - else + else - rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & - / (propRadius - innerZeroThrustRadius)) - fact = one / propRadius - fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & - / (two * pi * region%cellRadii(region%nCellIDs)) - Ftmp = volRef(i, j, k) * fact * fact2 + rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & + / (propRadius - innerZeroThrustRadius)) + fact = one / propRadius + fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & + / (two * pi * region%cellRadii(region%nCellIDs)) + Ftmp = volRef(i, j, k) * fact * fact2 - thrustSum = thrustSum + Ftmp + thrustSum = thrustSum + Ftmp - region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec + region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec - swirlFact2 = distribPDfactor / pi / region%cellRadii(region%nCellIDs) & - * propRadius * swirlFact - FTang = swirlFact2 * fact * fact2 - Swtmp = volRef(i, j, k) * FTang + swirlFact2 = distribPDfactor / pi / region%cellRadii(region%nCellIDs) & + * propRadius * swirlFact + FTang = swirlFact2 * fact * fact2 + Swtmp = volRef(i, j, k) * FTang - swirlSum = swirlSum + Swtmp + swirlSum = swirlSum + Swtmp - region%swirlVec(:, region%nCellIDs) = Swtmp & - * region%cellTangentials(:, region%nCellIDs) - end if - end if + region%swirlVec(:, region%nCellIDs) = Swtmp & + * region%cellTangentials(:, region%nCellIDs) + end if + end if end if end if end if From 8db8741ba7939626814df82180a1e512e158ab89 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 27 Feb 2025 14:37:27 +0000 Subject: [PATCH 15/49] update variable naming and inconsitencies --- src/adjoint/adjointDebug.F90 | 4 +-- src/adjoint/adjointUtils.F90 | 4 +-- src/bcdata/BCData.F90 | 16 ++++----- src/modules/actuatorRegionData.F90 | 9 +++--- src/solver/actuatorRegion.F90 | 4 +-- src/solver/residuals.F90 | 52 +++++++++++++++--------------- 6 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/adjoint/adjointDebug.F90 b/src/adjoint/adjointDebug.F90 index 0f7bf2d9e..24119b4d8 100644 --- a/src/adjoint/adjointDebug.F90 +++ b/src/adjoint/adjointDebug.F90 @@ -558,8 +558,8 @@ subroutine printADSeeds(nn, level, sps) ! And the reverse seeds in the actuator zones do i = 1, nActuatorRegions - write (*, *) 'actuatorRegionsd(i)%F ', actuatorRegionsd(i)%f - write (*, *) 'actuatorRegionsd(i)%T ', actuatorRegionsd(i)%t + write (*, *) 'actuatorRegionsd(i)%Force ', actuatorRegionsd(i)%force + write (*, *) 'actuatorRegionsd(i)%Torque ', actuatorRegionsd(i)%torque end do end subroutine printADSeeds diff --git a/src/adjoint/adjointUtils.F90 b/src/adjoint/adjointUtils.F90 index 97190cb7a..68dc4d8fe 100644 --- a/src/adjoint/adjointUtils.F90 +++ b/src/adjoint/adjointUtils.F90 @@ -1074,8 +1074,8 @@ subroutine zeroADSeeds(nn, level, sps) ! And the reverse seeds in the actuator zones do i = 1, nActuatorRegions - actuatorRegionsd(i)%F = zero - actuatorRegionsd(i)%T = zero + actuatorRegionsd(i)%force = zero + actuatorRegionsd(i)%torque = zero actuatorRegionsd(i)%thrust = zero actuatorRegionsd(i)%heat = zero actuatorRegionsd(i)%volume = zero diff --git a/src/bcdata/BCData.F90 b/src/bcdata/BCData.F90 index 037000328..4ebb6dd75 100644 --- a/src/bcdata/BCData.F90 +++ b/src/bcdata/BCData.F90 @@ -1485,10 +1485,10 @@ subroutine setBCData(bcDataNamesIn, bcDataIn, famLists, sps, & varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) if (trim(varName) == "Thrust") then - actuatorRegions(iRegion)%f = actuatorRegions(iRegion)%axisVec * & + actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & bcDataIn(iVar) else if (trim(varName) == "Torque") then - actuatorRegions(iRegion)%t = bcDataIn(iVar) + actuatorRegions(iRegion)%torque = bcDataIn(iVar) else if (trim(varName) == "Heat") then actuatorRegions(iRegion)%heat = bcDataIn(iVar) end if @@ -1583,13 +1583,13 @@ subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) if (trim(varName) == "Thrust") then - actuatorRegions(iRegion)%f = actuatorRegions(iRegion)%axisVec * & + actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & bcDataIn(iVar) - actuatorRegionsd(iRegion)%f = actuatorRegions(iRegion)%axisVec * & + actuatorRegionsd(iRegion)%force = actuatorRegions(iRegion)%axisVec * & bcDataInd(iVar) else if (trim(varName) == "Torque") then - actuatorRegions(iRegion)%t = bcDataIn(iVar) - actuatorRegionsd(iRegion)%t = bcDataInd(iVar) + actuatorRegions(iRegion)%torque = bcDataIn(iVar) + actuatorRegionsd(iRegion)%torque = bcDataInd(iVar) else if (trim(varName) == "Heat") then actuatorRegions(iRegion)%heat = bcDataIn(iVar) actuatorRegionsd(iRegion)%heat = bcDataInd(iVar) @@ -1689,9 +1689,9 @@ subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & if (trim(varName) == "Thrust") then bcDataInd(ivar) = & - sum(actuatorRegions(iRegion)%axisVec * actuatorRegionsd(iRegion)%f) + sum(actuatorRegions(iRegion)%axisVec * actuatorRegionsd(iRegion)%force) else if (trim(varName) == "Torque") then - bcDataInd(ivar) = actuatorRegionsd(iRegion)%t + bcDataInd(ivar) = actuatorRegionsd(iRegion)%torque else if (trim(varName) == "Heat") then bcDataInd(ivar) = actuatorRegionsd(iRegion)%heat end if diff --git a/src/modules/actuatorRegionData.F90 b/src/modules/actuatorRegionData.F90 index 5ff216c46..fcf8effb7 100644 --- a/src/modules/actuatorRegionData.F90 +++ b/src/modules/actuatorRegionData.F90 @@ -16,8 +16,9 @@ module actuatorRegionData ! The total number of cells included this proc has integer(kind=intType) :: nCellIDs - ! F is the force vector to be applied on this region - real(kind=realType) :: F(3) + ! the force vector to be applied on this region + ! this is equal to torque * axisVec + real(kind=realType) :: force(3) ! thrust is the total thrust magnitude to be applied on this region real(kind=realType) :: thrust @@ -29,8 +30,8 @@ module actuatorRegionData real(kind=realType) :: spinnerRadius real(kind=realType) :: rootDragFactor - ! T is the total torque to be applied on this region - real(kind=realType) :: T + ! magnitude of the total torque to be applied on this region + real(kind=realType) :: torque ! vector that determines the direction of the applied torque and force real(kind=realType), dimension(3) :: axisVec real(kind=realType), dimension(:, :), pointer :: thrustVec diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 9c55dca54..d5a8934c8 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -95,7 +95,7 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & region%actType = actType region%famName = famName region%famID = famID - region%T = torque + region%torque = torque region%heat = heat region%relaxStart = relaxStart region%relaxEnd = relaxEnd @@ -112,7 +112,7 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & axisVec = axisVec / axisVecNorm - region%F = axisVec * thrust + region%force = axisVec * thrust region%thrust = thrust region%axisVec = axisVec diff --git a/src/solver/residuals.F90 b/src/solver/residuals.F90 index 6376c3fef..ef3ca62a4 100644 --- a/src/solver/residuals.F90 +++ b/src/solver/residuals.F90 @@ -383,8 +383,8 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) ! If using the uniform force distribution if (actuatorRegions(iRegion)%actType == 'uniform') then - ! Compute the constant force factor - F_fact = factor * actuatorRegions(iRegion)%F / actuatorRegions(iRegion)%volume / pRef + ! Compute the constant force factor + F_fact = factor * actuatorRegions(iRegion)%force / actuatorRegions(iRegion)%volume / pRef end if ! Heat factor. This is heat added per unit volume per unit time @@ -396,36 +396,36 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) ! If using the uniform force distribution if (actuatorRegions(iRegion)%actType == 'uniform') then - !$AD II-LOOP - do ii = iStart, iEnd + !$AD II-LOOP + do ii = iStart, iEnd - ! Extract the cell ID. - i = actuatorRegions(iRegion)%cellIDs(1, ii) - j = actuatorRegions(iRegion)%cellIDs(2, ii) - k = actuatorRegions(iRegion)%cellIDs(3, ii) + ! Extract the cell ID. + i = actuatorRegions(iRegion)%cellIDs(1, ii) + j = actuatorRegions(iRegion)%cellIDs(2, ii) + k = actuatorRegions(iRegion)%cellIDs(3, ii) - ! This actually gets the force - FTmp = vol(i, j, k) * F_fact + ! This actually gets the force + FTmp = vol(i, j, k) * F_fact - Vx = w(i, j, k, iVx) - Vy = w(i, j, k, iVy) - Vz = w(i, j, k, iVz) + Vx = w(i, j, k, iVx) + Vy = w(i, j, k, iVy) + Vz = w(i, j, k, iVz) - ! this gets the heat addition rate - QTmp = vol(i, j, k) * Q_fact + ! this gets the heat addition rate + QTmp = vol(i, j, k) * Q_fact - if (res) then - ! Momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp + if (res) then + ! Momentum residuals + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp - ! energy residuals - dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp - else - ! Add in the local power contribution: - pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim - end if - end do + ! energy residuals + dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & + Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp + else + ! Add in the local power contribution: + pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim + end if + end do end if ! If using the simple propeller force distribution From 6ce5859e477cf9b5f1bd6bd0bcdd9e35109997fe Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 27 Feb 2025 14:38:09 +0000 Subject: [PATCH 16/49] update AD files --- src/adjoint/Makefile_tapenade | 4 +- src/adjoint/outputForward/residuals_d.f90 | 167 +++++++------- src/adjoint/outputReverse/residuals_b.f90 | 206 +++++++++--------- .../outputReverseFast/residuals_fast_b.f90 | 93 ++++---- src/modules/diffSizes.f90 | 10 +- 5 files changed, 252 insertions(+), 228 deletions(-) diff --git a/src/adjoint/Makefile_tapenade b/src/adjoint/Makefile_tapenade index 10472bc30..4042a9fe2 100644 --- a/src/adjoint/Makefile_tapenade +++ b/src/adjoint/Makefile_tapenade @@ -183,8 +183,8 @@ sa%saViscous(w, vol, si, sj, sk, rlv, scratch) > \ sa%saResScale(scratch, dw) > \ (dw) \ \ -residuals%sourceTerms_block(w, pref, uref, plocal, dw, vol, actuatorRegions%F, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) > \ - (w, pref, uref, plocal, dw, vol, actuatorRegions%F, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) \ +residuals%sourceTerms_block(w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) > \ + (w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) \ \ residuals%initres_block(dw, fw, flowDoms%w, flowDoms%vol, dscalar, dvector) > \ (dw, fw, flowDoms%w, flowDoms%vol, dscalar, dvector) \ diff --git a/src/adjoint/outputForward/residuals_d.f90 b/src/adjoint/outputForward/residuals_d.f90 index 944e6d7c5..c8f79ea77 100644 --- a/src/adjoint/outputForward/residuals_d.f90 +++ b/src/adjoint/outputForward/residuals_d.f90 @@ -340,11 +340,13 @@ end subroutine residual_block ! differentiation of sourceterms_block in forward (tangent) mode (with options i4 dr8 r8): ! variations of useful results: *dw plocal -! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.f -! actuatorregions.thrust actuatorregions.heat actuatorregions.volume plocal +! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force +! actuatorregions.thrust actuatorregions.heat actuatorregions.volume +! plocal ! rw status of diff variables: uref:in pref:in *w:in *dw:in-out -! *vol:in actuatorregions.f:in actuatorregions.thrust:in actuatorregions.heat:in -! actuatorregions.volume:in plocal:in-out +! *vol:in actuatorregions.force:in actuatorregions.thrust:in +! actuatorregions.heat:in actuatorregions.volume:in +! plocal:in-out ! plus diff mem management of: w:in dw:in vol:in subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) ! apply the source terms for the given block. assume that the @@ -355,6 +357,8 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) use flowvarrefstate, only : pref, prefd, uref, urefd, lref use communication use iteration, only : ordersconverged + use diffsizes +! hint: isize1oftemp should be the size of dimension 1 of array temp implicit none ! input integer(kind=inttype), intent(in) :: nn, iregion @@ -370,6 +374,8 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) real(kind=realtype) :: temp real(kind=realtype) :: temp0 real(kind=realtype) :: temp1 + real(kind=realtype), dimension(isize1oftemp) :: temp2 + real(kind=realtype), dimension(isize1oftemp) :: temp3 redimd = uref*prefd + pref*urefd redim = pref*uref ! compute the relaxation factor based on the ordersconverged @@ -388,11 +394,14 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - temp = actuatorregions(iregion)%volume*pref - f_factd = factor*(actuatorregionsd(iregion)%f-actuatorregions(& -& iregion)%f*(pref*actuatorregionsd(iregion)%volume+& -& actuatorregions(iregion)%volume*prefd)/temp)/temp - f_fact = factor*(actuatorregions(iregion)%f/temp) + temp = actuatorregions(iregion)%volume*pref + f_factd = factor*(actuatorregionsd(iregion)%force-actuatorregions(& +& iregion)%force*(pref*actuatorregionsd(iregion)%volume+& +& actuatorregions(iregion)%volume*prefd)/temp)/temp + f_fact = factor*(actuatorregions(iregion)%force/temp) + else + f_factd = 0.0_8 + end if ! heat factor. this is heat added per unit volume per unit time temp = lref*lref*actuatorregions(iregion)%volume temp0 = temp*pref*uref @@ -401,50 +410,46 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) & lref**2*actuatorregionsd(iregion)%volume+temp*(uref*prefd+pref*& & urefd)))/temp0 q_fact = factor*temp1 - else - f_factd = 0.0_8 - q_factd = 0.0_8 - end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmpd = f_fact*vold(i, j, k) + vol(i, j, k)*f_factd - ftmp = vol(i, j, k)*f_fact - vxd = wd(i, j, k, ivx) - vx = w(i, j, k, ivx) - vyd = wd(i, j, k, ivy) - vy = w(i, j, k, ivy) - vzd = wd(i, j, k, ivz) - vz = w(i, j, k, ivz) + ftmpd = f_fact*vold(i, j, k) + vol(i, j, k)*f_factd + ftmp = vol(i, j, k)*f_fact + vxd = wd(i, j, k, ivx) + vx = w(i, j, k, ivx) + vyd = wd(i, j, k, ivy) + vy = w(i, j, k, ivy) + vzd = wd(i, j, k, ivz) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmpd = q_fact*vold(i, j, k) + vol(i, j, k)*q_factd - qtmp = vol(i, j, k)*q_fact - if (res) then + qtmpd = q_fact*vold(i, j, k) + vol(i, j, k)*q_factd + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*ftmpd(1) - ftmp(1& -& )*vxd - vy*ftmpd(2) - ftmp(2)*vyd - vz*ftmpd(3) - ftmp(3)*vzd & -& - qtmpd - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp - else + dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*ftmpd(1) - ftmp& +& (1)*vxd - vy*ftmpd(2) - ftmp(2)*vyd - vz*ftmpd(3) - ftmp(3)*& +& vzd - qtmpd + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - temp1 = vx*ftmp(1) + vy*ftmp(2) + vz*ftmp(3) - plocald = plocald + redim*(ftmp(1)*vxd+vx*ftmpd(1)+ftmp(2)*vyd+& -& vy*ftmpd(2)+ftmp(3)*vzd+vz*ftmpd(3)) + temp1*redimd - plocal = plocal + temp1*redim - end if - end do + temp1 = vx*ftmp(1) + vy*ftmp(2) + vz*ftmp(3) + plocald = plocald + redim*(ftmp(1)*vxd+vx*ftmpd(1)+ftmp(2)*vyd& +& +vy*ftmpd(2)+ftmp(3)*vzd+vz*ftmpd(3)) + temp1*redimd + plocal = plocal + temp1*redim + end if + end do end if ! if using the simple propeller force distribution if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then @@ -453,18 +458,16 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) i = actuatorregions(iregion)%cellids(1, ii) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) - ftmpd = (factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& actuatorregionsd(iregion)%thrust*pref-factor*actuatorregions(& -& iregion)%thrustvec(:, ii)*actuatorregions(iregion)%thrust*& -& prefd)/pref**2 - ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - ftmpd = ftmpd + (factor*actuatorregions(iregion)%swirlvec(:, ii)& -& *actuatorregionsd(iregion)%thrust*pref-factor*actuatorregions(& -& iregion)%swirlvec(:, ii)*actuatorregions(iregion)%thrust*prefd& -& )/pref**2 - ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref + temp2 = factor*actuatorregions(iregion)%thrustvec(:, ii) + temp1 = actuatorregions(iregion)%thrust/pref + ftmpd = temp2*(actuatorregionsd(iregion)%thrust-temp1*prefd)/& +& pref + ftmp = temp2*temp1 + temp3 = factor*actuatorregions(iregion)%swirlvec(:, ii) + temp1 = actuatorregions(iregion)%thrust/pref + ftmpd = ftmpd + temp3*(actuatorregionsd(iregion)%thrust-temp1*& +& prefd)/pref + ftmp = ftmp + temp3*temp1 vxd = wd(i, j, k, ivx) vx = w(i, j, k, ivx) vyd = wd(i, j, k, ivy) @@ -476,21 +479,22 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - ftmpd(1)*vx - ftmp& -& (1)*vxd - ftmpd(2)*vy - ftmp(2)*vyd - ftmpd(3)*vz - ftmp(3)*& + dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*ftmpd(1) - ftmp& +& (1)*vxd - vy*ftmpd(2) - ftmp(2)*vyd - vz*ftmpd(3) - ftmp(3)*& & vzd dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& & *vy - ftmp(3)*vz else ! add in the local power contribution: - plocald = plocald + (vxd*ftmp(1)+vx*ftmpd(1)+vyd*ftmp(2)+vy*& -& ftmpd(2)+vzd*ftmp(3)+vz*ftmpd(3))*redim + (vx*ftmp(1)+vy*& -& ftmp(2)+vz*ftmp(3))*redimd - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + temp1 = vx*ftmp(1) + vy*ftmp(2) + vz*ftmp(3) + plocald = plocald + redim*(ftmp(1)*vxd+vx*ftmpd(1)+ftmp(2)*vyd& +& +vy*ftmpd(2)+ftmp(3)*vzd+vz*ftmpd(3)) + temp1*redimd + plocal = plocal + temp1*redim end if end do end if end subroutine sourceterms_block_d + subroutine sourceterms_block(nn, res, iregion, plocal) ! apply the source terms for the given block. assume that the ! block pointers are already set. @@ -523,47 +527,48 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -!$ad ii-loop ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& -& iregion)%volume/pref + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref + end if ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) - end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then - do ii=istart,iend +!$ad ii-loop + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact - if (res) then + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp - else + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do end if ! if using the simple propeller force distribution if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then +!$ad ii-loop do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) diff --git a/src/adjoint/outputReverse/residuals_b.f90 b/src/adjoint/outputReverse/residuals_b.f90 index c9e64ded5..d800bab56 100644 --- a/src/adjoint/outputReverse/residuals_b.f90 +++ b/src/adjoint/outputReverse/residuals_b.f90 @@ -335,13 +335,16 @@ subroutine residual_block() end subroutine residual_block ! differentiation of sourceterms_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): -! gradient of useful results: uref pref *w *dw *vol actuatorregions.f -! actuatorregions.thrust actuatorregions.heat actuatorregions.volume plocal -! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.f -! actuatorregions.thrust actuatorregions.heat actuatorregions.volume plocal +! gradient of useful results: uref pref *w *dw *vol actuatorregions.force +! actuatorregions.thrust actuatorregions.heat actuatorregions.volume +! plocal +! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force +! actuatorregions.thrust actuatorregions.heat actuatorregions.volume +! plocal ! rw status of diff variables: uref:incr pref:incr *w:incr *dw:in-out -! *vol:incr actuatorregions.f:incr actuatorregions.thrust actuatorregions.heat:incr -! actuatorregions.volume:incr plocal:in-out +! *vol:incr actuatorregions.force:incr actuatorregions.thrust:incr +! actuatorregions.heat:incr actuatorregions.volume:incr +! plocal:in-out ! plus diff mem management of: w:in dw:in vol:in subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) ! apply the source terms for the given block. assume that the @@ -365,7 +368,6 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) real(kind=realtype) :: ftmpd(3), vxd, vyd, vzd, f_factd(3), q_factd& & , qtmpd, redimd real(kind=realtype), dimension(3) :: tempd - real(kind=realtype) :: tempd3 real(kind=realtype) :: temp real(kind=realtype) :: tempd0 real(kind=realtype) :: temp0 @@ -392,15 +394,15 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& -& iregion)%volume/pref -! heat factor. this is heat added per unit volume per unit time - q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& -& iregion)%volume/(pref*uref*lref*lref) + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref call pushcontrol1b(0) else call pushcontrol1b(1) end if +! heat factor. this is heat added per unit volume per unit time + q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& +& iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) @@ -410,12 +412,10 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) else call pushcontrol1b(1) end if - q_factd = 0.0_8 - redimd = 0.0_8 - f_factd = 0.0_8 ! if using the simple propeller force distribution if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then redimd = 0.0_8 +!$bwd-of ii-loop do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) @@ -439,84 +439,81 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) ftmpd = ftmpd - dwd(i, j, k, imx:imz) else ftmpd = 0.0_8 - tempd3 = redim*plocald - vxd = ftmp(1)*tempd3 - ftmpd(1) = ftmpd(1) + vx*tempd3 - vyd = ftmp(2)*tempd3 - ftmpd(2) = ftmpd(2) + vy*tempd3 - vzd = ftmp(3)*tempd3 - ftmpd(3) = ftmpd(3) + vz*tempd3 + tempd1 = redim*plocald redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald + vxd = ftmp(1)*tempd1 + ftmpd(1) = ftmpd(1) + vx*tempd1 + vyd = ftmp(2)*tempd1 + ftmpd(2) = ftmpd(2) + vy*tempd1 + vzd = ftmp(3)*tempd1 + ftmpd(3) = ftmpd(3) + vz*tempd1 end if - tempd2 = sum(factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& ftmpd)/pref wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - tempd1 = sum(factor*actuatorregions(iregion)%swirlvec(:, ii)*& -& ftmpd)/pref + tempd1 = sum(actuatorregions(iregion)%swirlvec(:, ii)*ftmpd)*& +& factor/pref actuatorregionsd(iregion)%thrust = actuatorregionsd(iregion)%& -& thrust + tempd2 + tempd1 - prefd = prefd - actuatorregions(iregion)%thrust*tempd2/pref - & -& actuatorregions(iregion)%thrust*tempd1/pref +& thrust + tempd1 + prefd = prefd - actuatorregions(iregion)%thrust*tempd1/pref + tempd1 = sum(actuatorregions(iregion)%thrustvec(:, ii)*ftmpd)*& +& factor/pref + actuatorregionsd(iregion)%thrust = actuatorregionsd(iregion)%& +& thrust + tempd1 + prefd = prefd - actuatorregions(iregion)%thrust*tempd1/pref end do else redimd = 0.0_8 end if call popcontrol1b(branch) if (branch .eq. 0) then - f_factd = 0.0_8 q_factd = 0.0_8 + f_factd = 0.0_8 !$bwd-of ii-loop - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - if (res) then - ftmpd = 0.0_8 - ftmpd(1) = ftmpd(1) - vx*dwd(i, j, k, irhoe) - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - ftmpd(2) = ftmpd(2) - vy*dwd(i, j, k, irhoe) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - ftmpd(3) = ftmpd(3) - vz*dwd(i, j, k, irhoe) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) - qtmpd = -dwd(i, j, k, irhoe) - ftmpd = ftmpd - dwd(i, j, k, imx:imz) - else - ftmpd = 0.0_8 - tempd1 = redim*plocald - redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald - vxd = ftmp(1)*tempd1 - ftmpd(1) = ftmpd(1) + vx*tempd1 - vyd = ftmp(2)*tempd1 - ftmpd(2) = ftmpd(2) + vy*tempd1 - vzd = ftmp(3)*tempd1 - ftmpd(3) = ftmpd(3) + vz*tempd1 - qtmpd = 0.0_8 - end if - vold(i, j, k) = vold(i, j, k) + q_fact*qtmpd + sum(f_fact*ftmpd) - q_factd = q_factd + vol(i, j, k)*qtmpd - wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd - wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd - wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - f_factd = f_factd + vol(i, j, k)*ftmpd - end do + if (res) then + ftmpd = 0.0_8 + ftmpd(1) = ftmpd(1) - vx*dwd(i, j, k, irhoe) + vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) + ftmpd(2) = ftmpd(2) - vy*dwd(i, j, k, irhoe) + vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) + ftmpd(3) = ftmpd(3) - vz*dwd(i, j, k, irhoe) + vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) + qtmpd = -dwd(i, j, k, irhoe) + ftmpd = ftmpd - dwd(i, j, k, imx:imz) + else + ftmpd = 0.0_8 + tempd1 = redim*plocald + redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald + vxd = ftmp(1)*tempd1 + ftmpd(1) = ftmpd(1) + vx*tempd1 + vyd = ftmp(2)*tempd1 + ftmpd(2) = ftmpd(2) + vy*tempd1 + vzd = ftmp(3)*tempd1 + ftmpd(3) = ftmpd(3) + vz*tempd1 + qtmpd = 0.0_8 + end if + vold(i, j, k) = vold(i, j, k) + q_fact*qtmpd + sum(f_fact*ftmpd) + q_factd = q_factd + vol(i, j, k)*qtmpd + wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd + wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd + wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd + f_factd = f_factd + vol(i, j, k)*ftmpd + end do else - f_factd = 0.0_8 q_factd = 0.0_8 + f_factd = 0.0_8 end if - call popcontrol1b(branch) - if (branch .eq. 0) then - tempd = factor*f_factd/(actuatorregions(iregion)%volume*pref) - tempd0 = -(sum(actuatorregions(iregion)%f*tempd)/(& -& actuatorregions(iregion)%volume*pref)) temp = lref*lref*actuatorregions(iregion)%volume temp0 = temp*pref*uref tempd1 = factor*q_factd/temp0 @@ -524,13 +521,21 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) & tempd1 tempd2 = -(actuatorregions(iregion)%heat*tempd1/temp0) actuatorregionsd(iregion)%volume = actuatorregionsd(iregion)%volume & -& + lref**2*pref*uref*tempd2 + pref*tempd0 - prefd = prefd + uref*temp*tempd2 + actuatorregions(iregion)%volume*& -& tempd0 +& + lref**2*pref*uref*tempd2 + prefd = prefd + uref*temp*tempd2 urefd = urefd + pref*temp*tempd2 - actuatorregionsd(iregion)%f = actuatorregionsd(iregion)%f + & -& tempd - endif + call popcontrol1b(branch) + if (branch .eq. 0) then + tempd = factor*f_factd/(actuatorregions(iregion)%volume*pref) + actuatorregionsd(iregion)%force = actuatorregionsd(iregion)%force & +& + tempd + tempd0 = -(sum(actuatorregions(iregion)%force*tempd)/(& +& actuatorregions(iregion)%volume*pref)) + actuatorregionsd(iregion)%volume = actuatorregionsd(iregion)%& +& volume + pref*tempd0 + prefd = prefd + actuatorregions(iregion)%volume*tempd0 + end if + call popcontrol1b(branch) prefd = prefd + uref*redimd urefd = urefd + pref*redimd end subroutine sourceterms_block_b @@ -570,44 +575,45 @@ subroutine sourceterms_block(nn, res, iregion, plocal) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& -& iregion)%volume/pref + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref + end if ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) - end if -!$ad ii-loop ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then - do ii=istart,iend +!$ad ii-loop + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact - if (res) then + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp - else + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do end if ! if using the simple propeller force distribution if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then +!$ad ii-loop do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) diff --git a/src/adjoint/outputReverseFast/residuals_fast_b.f90 b/src/adjoint/outputReverseFast/residuals_fast_b.f90 index 59ec18ae0..f57c2745a 100644 --- a/src/adjoint/outputReverseFast/residuals_fast_b.f90 +++ b/src/adjoint/outputReverseFast/residuals_fast_b.f90 @@ -362,11 +362,17 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: if (ordersconverged .lt. actuatorregions(iregion)%relaxstart) then +myIntPtr = myIntPtr + 1 + myIntStack(myIntPtr) = 0 factor = zero else if (ordersconverged .gt. actuatorregions(iregion)%relaxend) & & then +myIntPtr = myIntPtr + 1 + myIntStack(myIntPtr) = 1 factor = one else +myIntPtr = myIntPtr + 1 + myIntStack(myIntPtr) = 1 ! in between ostart = actuatorregions(iregion)%relaxstart oend = actuatorregions(iregion)%relaxend @@ -375,9 +381,10 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& -& iregion)%volume/pref + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref end if +! heat factor. this is heat added per unit volume per unit time ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) @@ -391,6 +398,7 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) end if ! if using the simple propeller force distribution if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then +!$bwd-of ii-loop do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) @@ -418,28 +426,30 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) myIntPtr = myIntPtr - 1 if (branch .eq. 0) then !$bwd-of ii-loop - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact + ftmp = vol(i, j, k)*f_fact ! this gets the heat addition rate - if (res) then - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) - else - vxd = 0.0_8 - vyd = 0.0_8 - vzd = 0.0_8 - end if - wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd - wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd - wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - end do + if (res) then + vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) + vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) + vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) + else + vxd = 0.0_8 + vyd = 0.0_8 + vzd = 0.0_8 + end if + wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd + wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd + wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd + end do end if +branch = myIntStack(myIntPtr) + myIntPtr = myIntPtr - 1 end subroutine sourceterms_block_fast_b subroutine sourceterms_block(nn, res, iregion, plocal) @@ -477,44 +487,45 @@ subroutine sourceterms_block(nn, res, iregion, plocal) ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%f/actuatorregions(& -& iregion)%volume/pref + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref + end if ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) - end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -!$ad ii-loop ! if using the uniform force distribution if (actuatorregions(iregion)%acttype .eq. 'uniform') then - do ii=istart,iend +!$ad ii-loop + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact - if (res) then + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp - else + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& +& *vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do end if ! if using the simple propeller force distribution if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then +!$ad ii-loop do ii=istart,iend ! extract the cell id. i = actuatorregions(iregion)%cellids(1, ii) diff --git a/src/modules/diffSizes.f90 b/src/modules/diffSizes.f90 index b9e12494e..4641ab4dd 100644 --- a/src/modules/diffSizes.f90 +++ b/src/modules/diffSizes.f90 @@ -3,7 +3,7 @@ module diffSizes implicit none save - ! These are the diff sizes reqruied for the forward mode AD + ! These are the diff sizes required for the forward mode AD integer(kind=intType), parameter :: ISIZE3ofviscsubface = 3 integer(kind=intType) :: ISIZE1OFDrfbcdata @@ -13,7 +13,7 @@ module diffSizes integer(kind=intType) :: ISIZE3OFDrfflowdoms integer(kind=intType) :: ISIZE1OFDrfflowdoms_bcdata - ! These are the diff sizes reqruied for the reverse mode AD + ! These are the diff sizes required for the reverse mode AD integer(kind=intType) :: ISIZE3OFDrfrlv, ISIZE2OFDrfrlv, ISIZE1OFDrfrlv integer(kind=intType) :: ISIZE4OFDrfw, ISIZE3OFDrfw, ISIZE2OFDrfw, ISIZE1OFDrfw integer(kind=intType) :: ISIZE4OFDrffw, ISIZE3OFDrffw, ISIZE2OFDrffw, ISIZE1OFDrffw @@ -68,7 +68,7 @@ module diffSizes integer(kind=intType) :: ISIZE2OFDrfbmtk1, ISIZE2OFDrfbvtk1 integer(kind=intType) :: ISIZE1OFDrfbmtk1, ISIZE1OFDrfbvtk1 - ! These are the diff sizes reqruied for the forward mode debug + ! These are the diff sizes required for the forward mode debug integer(kind=intType) :: ISIZE1OFDrfDrfbcdata_m, ISIZE2OFDrfDrfbcdata_m, ISIZE3OFDrfDrfbcdata_m integer(kind=intType) :: ISIZE1OFDrfDrfbcdata_fp, ISIZE2OFDrfDrfbcdata_fp, ISIZE3OFDrfDrfbcdata_fp integer(kind=intType) :: ISIZE1OFDrfDrfbcdata_fv, ISIZE2OFDrfDrfbcdata_fv, ISIZE3OFDrfDrfbcdata_fv @@ -107,7 +107,9 @@ module diffSizes integer(kind=intType) :: ISIZE1OFDu1, ISIZE1OFDu2, ISIZE1OFDu3 integer(kind=intType) :: ISIZE1OFLeft, ISIZE1OFRight, ISIZE1OFFlux - ! These are the diff sizes reqruied for the reverse mode + integer(kind=intType) :: ISIZE1OFtemp + + ! These are the diff sizes required for the reverse mode integer(kind=intType) :: ISIZE1OFDRFCOEFTIME integer(kind=intType) :: ISIZE1OFDRFDTL, ISIZE2OFDRFDTL, ISIZE3OFDRFDTL integer(kind=intType) :: ISIZE1OFDRFDRFVISCSUBFACE_UTAU, ISIZE2OFDRFDRFVISCSUBFACE_UTAU From 13d83f852b5d4688ce6717a8e1e108ce867863b2 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 27 Feb 2025 14:38:58 +0000 Subject: [PATCH 17/49] update actuator test --- tests/reg_tests/test_actuator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/reg_tests/test_actuator.py b/tests/reg_tests/test_actuator.py index 25364fa90..10d934ac9 100644 --- a/tests/reg_tests/test_actuator.py +++ b/tests/reg_tests/test_actuator.py @@ -94,6 +94,7 @@ def setUp(self): actuatorFile = os.path.join(baseDir, "../../input_files/actuator_test_disk.xyz") self.CFDSolver.addActuatorRegion( actuatorFile, + "uniform", np.array([0, 0, 0]), np.array([1, 0, 0]), "actuator_region", From a9ead6a4d000a94f177b5dd3d9b66f366cba44a9 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 27 Feb 2025 14:52:01 +0000 Subject: [PATCH 18/49] black --- adflow/pyADflow.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index f723ce2cb..54638efa3 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -850,7 +850,7 @@ def addActuatorRegion( rootDragFactor=0.0, relaxStart=None, relaxEnd=None, - coordXfer=None + coordXfer=None, ): """Add an actuator zone with a uniform force distribution or add an actuator-disk zone representing a propeller. The zone is defined by @@ -869,7 +869,7 @@ def addActuatorRegion( propeller-wing interaction" by Chauhan and Martins for more. This applies axis-symmetric (but radially varying) forces. - The surface defines the physical extent of the + The surface defines the physical extent of the region over which to apply the source terms. The plot3d file may be multi-block but all the surface normals must point outside and no additional surfaces can be inside. Internally, we find all of the CFD @@ -930,7 +930,7 @@ def addActuatorRegion( thrust, and also to define the propeller axis for the propeller model. The propeller axis is used to compute the radii of the cells in the actuator-disk zone and also to calculate the directions for axial and - tangential forces. + tangential forces. familyName : str The name to be associated with the functions defined on this region. @@ -1040,14 +1040,32 @@ def addActuatorRegion( if relaxEnd is None and relaxStart is not None: raise Error("relaxEnd must be given is relaxStart is specified") - if actType != 'uniform' and actType != 'simpleProp': + if actType != "uniform" and actType != "simpleProp": raise Error("actType must be 'uniform' or 'simpleProp'") # Now continue to fortran were we setup the actual region. self.adflow.actuatorregion.addactuatorregion( - pts.T, conn.T, actType, axis1, axis2, familyName, famID, thrust, torque, heat, - swirlFact, mDistribParam, nDistribParam, distribPDfactor, innerZeroThrustRadius, - propRadius, spinnerRadius, rootDragFactor, relaxStart, relaxEnd) + pts.T, + conn.T, + actType, + axis1, + axis2, + familyName, + famID, + thrust, + torque, + heat, + swirlFact, + mDistribParam, + nDistribParam, + distribPDfactor, + innerZeroThrustRadius, + propRadius, + spinnerRadius, + rootDragFactor, + relaxStart, + relaxEnd, + ) def writeActuatorRegions(self, fileName, outputDir=None): """ From bcbc6f34817d941069c8c5ef0b4ec994771f2eba Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 27 Feb 2025 21:45:24 +0000 Subject: [PATCH 19/49] order arguments --- adflow/pyADflow.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 54638efa3..ee998ced3 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -840,6 +840,10 @@ def addActuatorRegion( thrust=0.0, torque=0.0, heat=0.0, + relaxStart=None, + relaxEnd=None, + coordXfer=None, + # simpleProp specific parameters swirlFact=0.0, mDistribParam=1.0, nDistribParam=0.5, @@ -848,9 +852,6 @@ def addActuatorRegion( propRadius=0.1, spinnerRadius=0.0, rootDragFactor=0.0, - relaxStart=None, - relaxEnd=None, - coordXfer=None, ): """Add an actuator zone with a uniform force distribution or add an actuator-disk zone representing a propeller. The zone is defined by From 6bb42a3fb7890505724d823bd5841ceb65471ad3 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 27 Feb 2025 21:45:48 +0000 Subject: [PATCH 20/49] fprettify --- src/output/outputMod.F90 | 2 +- src/solver/actuatorRegion.F90 | 124 +++++++++++++++-------------- src/solver/residuals.F90 | 38 ++++----- src/solver/surfaceIntegrations.F90 | 8 +- 4 files changed, 87 insertions(+), 85 deletions(-) diff --git a/src/output/outputMod.F90 b/src/output/outputMod.F90 index 6214fae12..40c752127 100644 --- a/src/output/outputMod.F90 +++ b/src/output/outputMod.F90 @@ -1498,7 +1498,7 @@ subroutine storeSurfsolInBuffer(sps, buffer, nn, blockID, & select case (solName) - case (cgnsSkinFmag, cgnsStanton, cgnsYplus, & + case (cgnsSkinFmag, cgnsStanton, cgnsYplus, & cgnsSkinFx, cgnsSkinFy, cgnsSkinFz, cgnsForceInDragDir, cgnsForceInLiftDir, & cgnsSepSensor, cgnsSepSensorKs, cgnsSepSensorKsArea) diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index d5a8934c8..293d5607e 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -181,14 +181,14 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & allocate (region%cellIDs(3, nCellsLocal(1))) if (region%actType == 'simpleProp') then - ! Allocate sufficient space for the maximum possible number of cellIDs - allocate(region%cellTangentials(3, nCellsLocal(1))) - allocate(region%thrustVec(3, nCellsLocal(1))) - allocate(region%swirlVec(3, nCellsLocal(1))) - - ! Allocate sufficient space for the maximum possible number of cellIDs - allocate(region%cellRadii(nCellsLocal(1))) - region%cellRadii(:) = zero + ! Allocate sufficient space for the maximum possible number of cellIDs + allocate (region%cellTangentials(3, nCellsLocal(1))) + allocate (region%thrustVec(3, nCellsLocal(1))) + allocate (region%swirlVec(3, nCellsLocal(1))) + + ! Allocate sufficient space for the maximum possible number of cellIDs + allocate (region%cellRadii(nCellsLocal(1))) + region%cellRadii(:) = zero end if ! Now search for all the coordinate. Note that We have explictly @@ -232,14 +232,14 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & v1 = xCen - axis2 v2 = axisVec - v3(1) = (v1(2)*v2(3) - v1(3)*v2(2)) - v3(2) = (v1(3)*v2(1) - v1(1)*v2(3)) - v3(3) = (v1(1)*v2(2) - v1(2)*v2(1)) + v3(1) = (v1(2) * v2(3) - v1(3) * v2(2)) + v3(2) = (v1(3) * v2(1) - v1(1) * v2(3)) + v3(3) = (v1(1) * v2(2) - v1(2) * v2(1)) v3 = v3 / sqrt(v3(1)**2 + v3(2)**2 + v3(3)**2) region%cellTangentials(:, region%nCellIDs) = v3 ! Compute the dot product and subtract to get radius - dotP = v1(1)*v2(2) + v1(2)*v2(2) + v1(3)*v2(3) + dotP = v1(1) * v2(2) + v1(2) * v2(2) + v1(3) * v2(3) radVec = v1 - dotP * axisVec region%cellRadii(region%nCellIDs) = & sqrt(radVec(1)**2 + radVec(2)**2 + radVec(3)**2) @@ -251,15 +251,16 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec Swtmp = zero - region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) + region%swirlVec(:, region%nCellIDs) = & + Swtmp * region%cellTangentials(:, region%nCellIDs) else if (region%cellRadii(region%nCellIDs) < innerZeroThrustRadius) then rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & - / (propRadius - innerZeroThrustRadius)) + / (propRadius - innerZeroThrustRadius)) fact = rootDragFactor / propRadius fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & - / (two * pi * region%cellRadii(region%nCellIDs)) + / (two * pi * region%cellRadii(region%nCellIDs)) Ftmp = volRef(i, j, k) * fact * fact2 thrustSum = thrustSum + Ftmp @@ -267,15 +268,16 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec Swtmp = zero - region%swirlVec(:, region%nCellIDs) = Swtmp * region%cellTangentials(:, region%nCellIDs) + region%swirlVec(:, region%nCellIDs) = & + Swtmp * region%cellTangentials(:, region%nCellIDs) else rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & - / (propRadius - innerZeroThrustRadius)) + / (propRadius - innerZeroThrustRadius)) fact = one / propRadius fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & - / (two * pi * region%cellRadii(region%nCellIDs)) + / (two * pi * region%cellRadii(region%nCellIDs)) Ftmp = volRef(i, j, k) * fact * fact2 thrustSum = thrustSum + Ftmp @@ -289,8 +291,8 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & swirlSum = swirlSum + Swtmp - region%swirlVec(:, region%nCellIDs) = Swtmp & - * region%cellTangentials(:, region%nCellIDs) + region%swirlVec(:, region%nCellIDs) = & + Swtmp * region%cellTangentials(:, region%nCellIDs) end if end if end if @@ -314,33 +316,33 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & deallocate (tmp) if (region%actType == 'simpleProp') then - ! Resize the cellTangentials to the correct size now that we know the - ! correct exact number. - tmp2 => region%cellTangentials - allocate(region%cellTangentials(3, region%nCellIDs)) - region%cellTangentials = tmp2(:, 1:region%nCellIDs) - deallocate(tmp2) - - ! Resize the thrustVec to the correct size now that we know the - ! correct exact number. - tmp2 => region%thrustVec - allocate(region%thrustVec(3, region%nCellIDs)) - region%thrustVec = tmp2(:, 1:region%nCellIDs) - deallocate(tmp2) - - ! Resize the swirlVec to the correct size now that we know the - ! correct exact number. - tmp2 => region%swirlVec - allocate(region%swirlVec(3, region%nCellIDs)) - region%swirlVec = tmp2(:, 1:region%nCellIDs) - deallocate(tmp2) - - ! Resize the cellRadii to the correct size now that we know the - ! correct exact number. - tmp3 => region%cellRadii - allocate(region%cellRadii(region%nCellIDs)) - region%cellRadii = tmp3(1:region%nCellIDs) - deallocate(tmp3) + ! Resize the cellTangentials to the correct size now that we know the + ! correct exact number. + tmp2 => region%cellTangentials + allocate (region%cellTangentials(3, region%nCellIDs)) + region%cellTangentials = tmp2(:, 1:region%nCellIDs) + deallocate (tmp2) + + ! Resize the thrustVec to the correct size now that we know the + ! correct exact number. + tmp2 => region%thrustVec + allocate (region%thrustVec(3, region%nCellIDs)) + region%thrustVec = tmp2(:, 1:region%nCellIDs) + deallocate (tmp2) + + ! Resize the swirlVec to the correct size now that we know the + ! correct exact number. + tmp2 => region%swirlVec + allocate (region%swirlVec(3, region%nCellIDs)) + region%swirlVec = tmp2(:, 1:region%nCellIDs) + deallocate (tmp2) + + ! Resize the cellRadii to the correct size now that we know the + ! correct exact number. + tmp3 => region%cellRadii + allocate (region%cellRadii(region%nCellIDs)) + region%cellRadii = tmp3(1:region%nCellIDs) + deallocate (tmp3) end if ! Now go back and generate the total volume of the the cells we've flagged @@ -361,25 +363,25 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & call mpi_allreduce(volLocal, region%volume, 1, adflow_real, & MPI_SUM, adflow_comm_world, ierr) call ECHK(ierr, __FILE__, __LINE__) - write (*,*) "Total vol of actuator region is", region%volume + write (*, *) "Total vol of actuator region is", region%volume if (region%actType == 'simpleProp') then - write (*,*) "thrust sum is", thrustSum - call mpi_allreduce(thrustSum, region%totalThrustSum, 1, adflow_real, & - MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - write (*,*) "Total thrust magnitude (mpi sum) without scaling factor is", region%totalThrustSum + write (*, *) "thrust sum is", thrustSum + call mpi_allreduce(thrustSum, region%totalThrustSum, 1, adflow_real, & + MPI_SUM, adflow_comm_world, ierr) + call ECHK(ierr, __FILE__, __LINE__) + write (*, *) "Total thrust magnitude (mpi sum) without scaling factor is", region%totalThrustSum - write (*,*) "swirl sum is", swirlSum - call mpi_allreduce(swirlSum, region%totalSwirlSum, 1, adflow_real, & - MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - write (*,*) "Total swirl magnitude (mpi sum) without scaling factor is", region%totalSwirlSum + write (*, *) "swirl sum is", swirlSum + call mpi_allreduce(swirlSum, region%totalSwirlSum, 1, adflow_real, & + MPI_SUM, adflow_comm_world, ierr) + call ECHK(ierr, __FILE__, __LINE__) + write (*, *) "Total swirl magnitude (mpi sum) without scaling factor is", region%totalSwirlSum - region%thrustVec = region%thrustVec / region%totalThrustSum - region%swirlVec = region%swirlVec / region%totalThrustSum + region%thrustVec = region%thrustVec / region%totalThrustSum + region%swirlVec = region%swirlVec / region%totalThrustSum - deallocate(region%cellTangentials) + deallocate (region%cellTangentials) end if ! Final memory cleanup diff --git a/src/solver/residuals.F90 b/src/solver/residuals.F90 index ef3ca62a4..f869d5ab2 100644 --- a/src/solver/residuals.F90 +++ b/src/solver/residuals.F90 @@ -420,7 +420,7 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) ! energy residuals dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp + Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp else ! Add in the local power contribution: pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim @@ -430,33 +430,33 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) ! If using the simple propeller force distribution if (actuatorRegions(iRegion)%actType == 'simpleProp') then - !$AD II-LOOP - do ii=iStart, iEnd + !$AD II-LOOP + do ii = iStart, iEnd - ! Extract the cell ID. - i = actuatorRegions(iRegion)%cellIDs(1, ii) - j = actuatorRegions(iRegion)%cellIDs(2, ii) - k = actuatorRegions(iRegion)%cellIDs(3, ii) + ! Extract the cell ID. + i = actuatorRegions(iRegion)%cellIDs(1, ii) + j = actuatorRegions(iRegion)%cellIDs(2, ii) + k = actuatorRegions(iRegion)%cellIDs(3, ii) - Ftmp = factor * actuatorRegions(iRegion)%thrustVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef - Ftmp = Ftmp + factor * actuatorRegions(iRegion)%swirlVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef + Ftmp = factor * actuatorRegions(iRegion)%thrustVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef + Ftmp = Ftmp + factor * actuatorRegions(iRegion)%swirlVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef - Vx = w(i, j, k, iVx) - Vy = w(i, j, k, iVy) - Vz = w(i, j, k, iVz) + Vx = w(i, j, k, iVx) + Vy = w(i, j, k, iVy) + Vz = w(i, j, k, iVz) - if (res) then + if (res) then ! Momentum residuals dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp ! energy residuals - dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1)*Vx - Ftmp(2)*Vy - Ftmp(3)*Vz - else + dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & + Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz + else ! Add in the local power contribution: - pLocal = pLocal + (Vx*Ftmp(1) + Vy*Ftmp(2) + Vz*Ftmp(3))*reDim - end if - end do + pLocal = pLocal + (Vx * Ftmp(1) + Vy * Ftmp(2) + Vz * Ftmp(3)) * reDim + end if + end do end if end subroutine sourceTerms_block diff --git a/src/solver/surfaceIntegrations.F90 b/src/solver/surfaceIntegrations.F90 index 357bc18d4..e236eca7d 100644 --- a/src/solver/surfaceIntegrations.F90 +++ b/src/solver/surfaceIntegrations.F90 @@ -159,10 +159,10 @@ subroutine getCostFunctions(globalVals, funcValues) funcValues(costFuncSepSensorKs) = funcValues(costFuncSepSensorKs) + ks_comp funcValues(costFuncsepSensorKsArea) = funcValues(costFuncsepSensorKsArea) + & - ovrNTS * globalVals(iSepSensorKsArea, sps) * ks_comp * & - one / (one + exp(2 * sepSensorKsSharpness & - * (ks_comp + sepSensorKsOffset))) + & - ovrNTS * globalVals(iSepSensorArea, sps) + ovrNTS * globalVals(iSepSensorKsArea, sps) * ks_comp * & + one / (one + exp(2 * sepSensorKsSharpness & + * (ks_comp + sepSensorKsOffset))) + & + ovrNTS * globalVals(iSepSensorArea, sps) end if From 0d2189737d726278c74748f59e5eb23eea04fe19 Mon Sep 17 00:00:00 2001 From: Eytan Adler Date: Tue, 4 Mar 2025 11:35:53 -0500 Subject: [PATCH 21/49] Fix dot product typo in actuator disk setup --- src/solver/actuatorRegion.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 9c55dca54..602f59a71 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -239,7 +239,7 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & region%cellTangentials(:, region%nCellIDs) = v3 ! Compute the dot product and subtract to get radius - dotP = v1(1)*v2(2) + v1(2)*v2(2) + v1(3)*v2(3) + dotP = v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3) radVec = v1 - dotP * axisVec region%cellRadii(region%nCellIDs) = & sqrt(radVec(1)**2 + radVec(2)**2 + radVec(3)**2) From 88388052ea4ba8d6aa9406f0287d265ca8688ff6 Mon Sep 17 00:00:00 2001 From: Eytan Adler Date: Tue, 4 Mar 2025 11:41:51 -0500 Subject: [PATCH 22/49] Add warnings about the torque not working for uniform actuator region --- adflow/pyADflow.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 50e9cba96..4bd611de9 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -913,7 +913,7 @@ def addActuatorRegion( propeller-wing interaction" by Chauhan and Martins for more. This applies axis-symmetric (but radially varying) forces. - The surface defines the physical extent of the + The surface defines the physical extent of the region over which to apply the source terms. The plot3d file may be multi-block but all the surface normals must point outside and no additional surfaces can be inside. Internally, we find all of the CFD @@ -986,6 +986,7 @@ def addActuatorRegion( See below for a description of innerZeroThrustRadius.) torque : scalar, float + Torque does not work! If you want swirl, try the simpleProp actType. The total amount of torque to apply to the region, about the specified axis. This is only for the uniform actuator zone. @@ -1087,6 +1088,12 @@ def addActuatorRegion( if actType != 'uniform' and actType != 'simpleProp': raise Error("actType must be 'uniform' or 'simpleProp'") + # Torque input doesn't do anything, warn user if they try to change it + if actType == "uniform" and torque != 0.0 and self.comm.rank == 0: + ADFLOWWarning( + "The torque input does not work for the uniform actuator region. If swirl is desired, try using the simpleProp actuator region." + ) + # Now continue to fortran were we setup the actual region. self.adflow.actuatorregion.addactuatorregion( pts.T, conn.T, actType, axis1, axis2, familyName, famID, thrust, torque, heat, From 4745f0cea2183c56496143c435abe4f0ee6bbace Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 5 Mar 2025 16:26:02 +0000 Subject: [PATCH 23/49] update complex test --- tests/reg_tests/test_actuator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/reg_tests/test_actuator.py b/tests/reg_tests/test_actuator.py index 10d934ac9..bd13bca0f 100644 --- a/tests/reg_tests/test_actuator.py +++ b/tests/reg_tests/test_actuator.py @@ -682,6 +682,7 @@ def setUp(self): actuatorFile = os.path.join(baseDir, "../../input_files/actuator_test_disk.xyz") self.CFDSolver.addActuatorRegion( actuatorFile, + "uniform", np.array([0, 0, 0]), np.array([1, 0, 0]), "actuator_region", From f11d5f070dc54ba88407ef2367eb2efc2cbc8822 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Thu, 5 Jun 2025 15:05:04 +0200 Subject: [PATCH 24/49] Strip down current implementation in order to move initialization to python --- adflow/actuatorRegion.py | 294 +++++++++++++++++ adflow/pyADflow.py | 209 +----------- src/adjoint/adjointDebug.F90 | 1 - src/adjoint/adjointUtils.F90 | 2 - src/adjoint/outputForward/residuals_d.f90 | 231 +++++--------- src/adjoint/outputReverse/residuals_b.f90 | 300 ++++++------------ .../outputReverseFast/residuals_fast_b.f90 | 152 +++------ src/bcdata/BCData.F90 | 128 ++++---- src/f2py/adflow.pyf | 16 +- src/modules/actuatorRegionData.F90 | 27 +- src/solver/actuatorRegion.F90 | 236 +++----------- src/solver/residuals.F90 | 89 ++---- 12 files changed, 662 insertions(+), 1023 deletions(-) create mode 100644 adflow/actuatorRegion.py diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py new file mode 100644 index 000000000..6543be53e --- /dev/null +++ b/adflow/actuatorRegion.py @@ -0,0 +1,294 @@ +from abc import ABC, abstractmethod +from typing import Tuple + +import numpy as np +import numpy.typing as npt + + +class AbstractActuatorRegion(ABC): + @abstractmethod + def getEnclosingSurface(self) -> Tuple[npt.NDArray, npt.NDArray]: + points = np.array([[]]) + connectivity = np.array([]) + + return points, connectivity + + + + + +class UniformActuatorRegion(AbstractActuatorRegion): + def __init__(self, centerPoint: np.ndarray, thrustVector: np.ndarray, outerDiameter: float, regionDepth: float, thrust: float, heat: float): + if regionDepth <= 0: + raise ValueError('"depth" must be greater than 0.') + if outerDiameter <= 0: + raise ValueError('"outerDiameter" must be greater than 0.') + if thrust < 0: + raise ValueError('"thrust" must not be smaller than 0.') + if heat < 0: + raise ValueError('"heat" must not be smaller than 0.') + + self.centerPoint = centerPoint + self.thrustVector = thrustVector + self.outerDiameter = outerDiameter + self.regionDepth = regionDepth + + def getEnclosingSurface(self): + + points = np.array([ + [-3.83050025e-01, -7.20579146E-02, 2.27942117E-01], + [-3.83050025e-01, -7.75741546E-02, 2.63231562E-01], + [-3.83050025e-01, -8.20070252E-02, 3.00000018E-01], + [-3.83050025e-01, -7.75741458E-02, 3.36768473E-01], + [-3.83050025e-01, -7.20578975E-02, 3.72057917E-01], + [-3.83050025e-01, -3.67684649E-02, 2.22425870E-01], + [-3.83050025e-01, -3.95765026E-02, 2.60423519E-01], + [-3.83050025e-01, -4.18330517E-02, 3.00000016E-01], + [-3.83050025e-01, -3.95764964E-02, 3.39576512E-01], + [-3.83050025e-01, -3.67684530E-02, 3.77574161E-01], + [-3.83050025e-01, -3.19709897E-09, 2.17992992E-01], + [-3.83050025e-01, -1.60606457E-09, 2.58166964E-01], + [-3.83050025e-01, 1.25967157E-10, 3.00000014E-01], + [-3.83050025e-01, 1.46254111E-09, 3.41833064E-01], + [-3.83050025e-01, 2.65221633E-09, 3.82007035E-01], + [-3.83050025e-01, 3.67684591E-02, 2.22425867E-01], + [-3.83050025e-01, 3.95764998E-02, 2.60423516E-01], + [-3.83050025e-01, 4.18330521E-02, 3.00000014E-01], + [-3.83050025e-01, 3.95764993E-02, 3.39576511E-01], + [-3.83050025e-01, 3.67684580E-02, 3.77574160E-01], + [-3.83050025e-01, 7.20579095E-02, 2.27942112E-01], + [-3.83050025e-01, 7.75741523E-02, 2.63231557E-01], + [-3.83050025e-01, 8.20070258E-02, 3.00000014E-01], + [-3.83050025e-01, 7.75741486E-02, 3.36768470E-01], + [-3.83050025e-01, 7.20579021E-02, 3.72057916E-01], + [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], + [-3.83050013e-01, -6.77167528E-02, 4.63482739E-01], + [-3.83050013e-01, 5.85581126E-09, 4.77000011E-01], + [-3.83050013e-01, 6.77167636E-02, 4.63482735E-01], + [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], + [-3.83050025e-01, -7.20578975E-02, 3.72057917E-01], + [-3.83050025e-01, -3.67684530E-02, 3.77574161E-01], + [-3.83050025e-01, 2.65221633E-09, 3.82007035E-01], + [-3.83050025e-01, 3.67684580E-02, 3.77574160E-01], + [-3.83050025e-01, 7.20579021E-02, 3.72057916E-01], + [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], + [-3.83050025e-01, 7.20579095E-02, 2.27942112E-01], + [-3.83050013e-01, 1.63482725E-01, 2.32283254E-01], + [-3.83050025e-01, 7.75741523E-02, 2.63231557E-01], + [-3.83050013e-01, 1.77000000E-01, 3.00000015E-01], + [-3.83050025e-01, 8.20070258E-02, 3.00000014E-01], + [-3.83050013e-01, 1.63482724E-01, 3.67716775E-01], + [-3.83050025e-01, 7.75741486E-02, 3.36768470E-01], + [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], + [-3.83050025e-01, 7.20579021E-02, 3.72057916E-01], + [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], + [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], + [-3.83050013e-01, -1.63482733E-01, 2.32283272E-01], + [-2.51800004e-01, -1.63482733E-01, 2.32283272E-01], + [-3.83050013e-01, -1.77000000E-01, 3.00000032E-01], + [-2.51800004e-01, -1.77000000E-01, 3.00000032E-01], + [-3.83050013e-01, -1.63482718E-01, 3.67716789E-01], + [-2.51800004e-01, -1.63482718E-01, 3.67716789E-01], + [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], + [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], + [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], + [-3.83050013e-01, -6.77167795E-02, 1.36517295E-01], + [-3.83050013e-01, -1.15403979E-08, 1.23000013E-01], + [-3.83050013e-01, 6.77167582E-02, 1.36517286E-01], + [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], + [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], + [-2.51800004e-01, -6.77167795E-02, 1.36517295E-01], + [-2.51800004e-01, -1.15403980E-08, 1.23000013E-01], + [-2.51800004e-01, 6.77167582E-02, 1.36517286E-01], + [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], + [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], + [-3.83050013e-01, 1.63482725E-01, 2.32283254E-01], + [-3.83050013e-01, 1.77000000E-01, 3.00000015E-01], + [-3.83050013e-01, 1.63482724E-01, 3.67716775E-01], + [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], + [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], + [-2.51800004e-01, 1.63482725E-01, 2.32283254E-01], + [-2.51800004e-01, 1.77000000E-01, 3.00000015E-01], + [-2.51800004e-01, 1.63482724E-01, 3.67716775E-01], + [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], + [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], + [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], + [-3.83050013e-01, -6.77167528E-02, 4.63482739E-01], + [-2.51800004e-01, -6.77167528E-02, 4.63482739E-01], + [-3.83050013e-01, 5.85581126E-09, 4.77000011E-01], + [-2.51800004e-01, 5.85581115E-09, 4.77000011E-01], + [-3.83050013e-01, 6.77167636E-02, 4.63482735E-01], + [-2.51800004e-01, 6.77167636E-02, 4.63482735E-01], + [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], + [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], + [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], + [-3.83050025e-01, -7.20579146E-02, 2.27942117E-01], + [-3.83050013e-01, -6.77167795E-02, 1.36517295E-01], + [-3.83050025e-01, -3.67684649E-02, 2.22425870E-01], + [-3.83050013e-01, -1.15403979E-08, 1.23000013E-01], + [-3.83050025e-01, -3.19709897E-09, 2.17992992E-01], + [-3.83050013e-01, 6.77167582E-02, 1.36517286E-01], + [-3.83050025e-01, 3.67684591E-02, 2.22425867E-01], + [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], + [-3.83050025e-01, 7.20579095E-02, 2.27942112E-01], + [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], + [-3.83050013e-01, -1.63482733E-01, 2.32283272E-01], + [-3.83050013e-01, -1.77000000E-01, 3.00000032E-01], + [-3.83050013e-01, -1.63482718E-01, 3.67716789E-01], + [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], + [-3.83050025e-01, -7.20579146E-02, 2.27942117E-01], + [-3.83050025e-01, -7.75741546E-02, 2.63231562E-01], + [-3.83050025e-01, -8.20070252E-02, 3.00000018E-01], + [-3.83050025e-01, -7.75741458E-02, 3.36768473E-01], + [-3.83050025e-01, -7.20578975E-02, 3.72057917E-01], + [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], + [-2.51800001e-01, -7.20579146E-02, 2.27942117E-01], + [-2.51800004e-01, -1.63482733E-01, 2.32283272E-01], + [-2.51800001e-01, -7.75741546E-02, 2.63231562E-01], + [-2.51800004e-01, -1.77000000E-01, 3.00000032E-01], + [-2.51800001e-01, -8.20070252E-02, 3.00000018E-01], + [-2.51800004e-01, -1.63482718E-01, 3.67716789E-01], + [-2.51800001e-01, -7.75741458E-02, 3.36768473E-01], + [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], + [-2.51800001e-01, -7.20578975E-02, 3.72057917E-01], + [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], + [-2.51800001e-01, -7.20578975E-02, 3.72057917E-01], + [-2.51800004e-01, -6.77167528E-02, 4.63482739E-01], + [-2.51800001e-01, -3.67684530E-02, 3.77574161E-01], + [-2.51800004e-01, 5.85581115E-09, 4.77000011E-01], + [-2.51800001e-01, 2.65221622E-09, 3.82007035E-01], + [-2.51800004e-01, 6.77167636E-02, 4.63482735E-01], + [-2.51800001e-01, 3.67684580E-02, 3.77574160E-01], + [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], + [-2.51800001e-01, 7.20579021E-02, 3.72057916E-01], + [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], + [-2.51800004e-01, 1.63482725E-01, 2.32283254E-01], + [-2.51800004e-01, 1.77000000E-01, 3.00000015E-01], + [-2.51800004e-01, 1.63482724E-01, 3.67716775E-01], + [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], + [-2.51800001e-01, 7.20579095E-02, 2.27942112E-01], + [-2.51800001e-01, 7.75741523E-02, 2.63231557E-01], + [-2.51800001e-01, 8.20070258E-02, 3.00000014E-01], + [-2.51800001e-01, 7.75741486E-02, 3.36768470E-01], + [-2.51800001e-01, 7.20579021E-02, 3.72057916E-01], + [-2.51800001e-01, -7.20579146E-02, 2.27942117E-01], + [-2.51800001e-01, -3.67684649E-02, 2.22425870E-01], + [-2.51800001e-01, -3.19709907E-09, 2.17992992E-01], + [-2.51800001e-01, 3.67684591E-02, 2.22425867E-01], + [-2.51800001e-01, 7.20579095E-02, 2.27942112E-01], + [-2.51800001e-01, -7.75741546E-02, 2.63231562E-01], + [-2.51800001e-01, -3.95765026E-02, 2.60423519E-01], + [-2.51800001e-01, -1.60606466E-09, 2.58166964E-01], + [-2.51800001e-01, 3.95764998E-02, 2.60423516E-01], + [-2.51800001e-01, 7.75741523E-02, 2.63231557E-01], + [-2.51800001e-01, -8.20070252E-02, 3.00000018E-01], + [-2.51800001e-01, -4.18330517E-02, 3.00000016E-01], + [-2.51800001e-01, 1.25967032E-10, 3.00000014E-01], + [-2.51800001e-01, 4.18330521E-02, 3.00000014E-01], + [-2.51800001e-01, 8.20070258E-02, 3.00000014E-01], + [-2.51800001e-01, -7.75741458E-02, 3.36768473E-01], + [-2.51800001e-01, -3.95764964E-02, 3.39576512E-01], + [-2.51800001e-01, 1.46254098E-09, 3.41833064E-01], + [-2.51800001e-01, 3.95764993E-02, 3.39576511E-01], + [-2.51800001e-01, 7.75741486E-02, 3.36768470E-01], + [-2.51800001e-01, -7.20578975E-02, 3.72057917E-01], + [-2.51800001e-01, -3.67684530E-02, 3.77574161E-01], + [-2.51800001e-01, 2.65221622E-09, 3.82007035E-01], + [-2.51800001e-01, 3.67684580E-02, 3.77574160E-01], + [-2.51800001e-01, 7.20579021E-02, 3.72057916E-01], + [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], + [-2.51800004e-01, -6.77167795E-02, 1.36517295E-01], + [-2.51800004e-01, -1.15403980E-08, 1.23000013E-01], + [-2.51800004e-01, 6.77167582E-02, 1.36517286E-01], + [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], + [-2.51800001e-01, -7.20579146E-02, 2.27942117E-01], + [-2.51800001e-01, -3.67684649E-02, 2.22425870E-01], + [-2.51800001e-01, -3.19709907E-09, 2.17992992E-01], + [-2.51800001e-01, 3.67684591E-02, 2.22425867E-01], + [-2.51800001e-01, 7.20579095E-02, 2.27942112E-01], + ]) + + connectivity = np.array([ + [ 0, 1, 6, 5], + [ 1, 2, 7, 6], + [ 2, 3, 8, 7], + [ 3, 4, 9, 8], + [ 5, 6, 11, 10], + [ 6, 7, 12, 11], + [ 7, 8, 13, 12], + [ 8, 9, 14, 13], + [ 10, 11, 16, 15], + [ 11, 12, 17, 16], + [ 12, 13, 18, 17], + [ 13, 14, 19, 18], + [ 15, 16, 21, 20], + [ 16, 17, 22, 21], + [ 17, 18, 23, 22], + [ 18, 19, 24, 23], + [ 25, 26, 31, 30], + [ 26, 27, 32, 31], + [ 27, 28, 33, 32], + [ 28, 29, 34, 33], + [ 35, 36, 38, 37], + [ 37, 38, 40, 39], + [ 39, 40, 42, 41], + [ 41, 42, 44, 43], + [ 45, 46, 48, 47], + [ 47, 48, 50, 49], + [ 49, 50, 52, 51], + [ 51, 52, 54, 53], + [ 55, 56, 61, 60], + [ 56, 57, 62, 61], + [ 57, 58, 63, 62], + [ 58, 59, 64, 63], + [ 65, 66, 71, 70], + [ 66, 67, 72, 71], + [ 67, 68, 73, 72], + [ 68, 69, 74, 73], + [ 75, 76, 78, 77], + [ 77, 78, 80, 79], + [ 79, 80, 82, 81], + [ 81, 82, 84, 83], + [ 85, 86, 88, 87], + [ 87, 88, 90, 89], + [ 89, 90, 92, 91], + [ 91, 92, 94, 93], + [ 95, 96, 101, 100], + [ 96, 97, 102, 101], + [ 97, 98, 103, 102], + [ 98, 99, 104, 103], + [105, 106, 108, 107], + [107, 108, 110, 109], + [109, 110, 112, 111], + [111, 112, 114, 113], + [115, 116, 118, 117], + [117, 118, 120, 119], + [119, 120, 122, 121], + [121, 122, 124, 123], + [125, 126, 131, 130], + [126, 127, 132, 131], + [127, 128, 133, 132], + [128, 129, 134, 133], + [135, 136, 141, 140], + [136, 137, 142, 141], + [137, 138, 143, 142], + [138, 139, 144, 143], + [140, 141, 146, 145], + [141, 142, 147, 146], + [142, 143, 148, 147], + [143, 144, 149, 148], + [145, 146, 151, 150], + [146, 147, 152, 151], + [147, 148, 153, 152], + [148, 149, 154, 153], + [150, 151, 156, 155], + [151, 152, 157, 156], + [152, 153, 158, 157], + [153, 154, 159, 158], + [160, 161, 166, 165], + [161, 162, 167, 166], + [162, 163, 168, 167], + [163, 164, 169, 168], + ]) + + return points, connectivity diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index b09e42f41..c4a9a3493 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -33,6 +33,7 @@ from . import MExt import hashlib from collections import OrderedDict +from .actuatorRegion import AbstractActuatorRegion class ADFLOWWarning(object): @@ -360,6 +361,8 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"): print("| %-30s: %10.3f sec" % ("Total Init Time", finalInitTime - startInitTime)) print("+--------------------------------------------------+") + self.actuatorRegions = list() + def __del__(self): """ Clean up allocated memory if necessary @@ -832,186 +835,15 @@ def addIntegrationSurface(self, fileName, familyName, isInflow=True, coordXfer=N def addActuatorRegion( self, - fileName, - actType, - axis1, - axis2, + actuatorRegion: AbstractActuatorRegion, familyName, - thrust=0.0, - torque=0.0, - heat=0.0, relaxStart=None, relaxEnd=None, - coordXfer=None, - # simpleProp specific parameters - swirlFact=0.0, - mDistribParam=1.0, - nDistribParam=0.5, - distribPDfactor=0.5, - innerZeroThrustRadius=0.0, - propRadius=0.1, - spinnerRadius=0.0, - rootDragFactor=0.0, ): - """Add an actuator zone with a uniform force distribution or add - an actuator-disk zone representing a propeller. The zone is defined by - the (closed) supplied surface in the plot3d file "fileName". The type - is set with the string "actType" as either 'uniform' or 'simpleProp'. - - For the uniform distribution (i.e., actType = 'uniform'): - The specified thrust is applied uniformly over the specified zone. - - For the propeller model (i.e., actType = 'simpleProp'): - The radial distributions of the axial and tangential forces can be tuned - using the parameters. For the distributions, the models used by Hoekstra - in "A RANS-based analysis tool for ducted propeller systems in open water - condition" [International Shipbuilding Progress, 2006] are used here. - See "RANS-based aerodynamic shape optimization of a wing considering - propeller-wing interaction" by Chauhan and Martins - for more. This applies axis-symmetric (but radially varying) forces. - - The surface defines the physical extent of the - region over which to apply the source terms. The plot3d file may be - multi-block but all the surface normals must point outside and no - additional surfaces can be inside. Internally, we find all of the CFD - volume cells that have their center inside this closed surface and - apply the source terms over these cells. This surface is only used with - the original mesh coordinates to mark the internal CFD cells, and we - keep using these cells even if the geometric design and the mesh - coordinates change. For example, the marked cells can lie outside of - the original closed surface after a large design change, but we will - still use the cells that were inside the surface with the baseline - design. - - axis1 and axis2 define the vector that we use to determine the - direction of the thrust addition. Internally, we compute a - vector by $axisVec = axis2-axis1$ and then we normalize this - vector. When adding the thrust terms, the direction of the thrust - is obtained by multiplying the thrust magnitude by this vector. - - Optionally, the source terms in the actuator zone can be - gradually ramped up as the solution converges. This continuation - approach can be more robust but the users should be careful with - the side effects of partially converged solutions. This behavior - can be controlled by relaxStart and relaxEnd parameters. By - default, the full magnitude of the source terms are added. - relaxStart controls when the continuation starts ramping up. - The value represents the relative convergence in a log10 basis. - So relaxStart = 2 means the source terms will be inactive until - the residual is decreased by a factor of 100 compared to free - stream conditions. The source terms are ramped to the full - magnitude at relaxEnd. E.g., a relaxEnd value of 4 would - result in the full source terms after a relative reduction of - 1e4 in the total residuals. If relaxStart is not provided, but - relaxEnd is provided, then the relaxStart is assumed to be 0. - If both are not provided, we do not do ramping and just activate - the full source terms from the beginning. When this continuation - is used, we internally ramp up the magnitude of the source terms - monotonically to prevent oscillations; i.e., decrease in the total - residuals increase the source term magnitudes, but an increase - in the residuals do not reduce the source terms back down. - - Parameters - ---------- - - fileName : str - The surface Plot3D file (multiblock ascii) defining the closed - region to which the forces are to be applied. - - actType : str - The type of force distribution. - Uniform ('uniform') or propeller ('simpleProp'). - - axis1 : numpy array, length 3 - The physical location of the start of the thrust or propeller axis (x,y,z). - - axis2 : numpy array, length 3 - The physical location of the end of the thrust or propeller axis (x,y,z). - The axis1 and axis2 points are used to define the direction of the - thrust, and also to define the propeller axis for the propeller model. - The propeller axis is used to compute the radii of the cells in the - actuator-disk zone and also to calculate the directions for axial and - tangential forces. - - familyName : str - The name to be associated with the functions defined on this region. - - thrust : scalar - The total magnitude of the (axial) thrust to apply to the region, - in the direction of axis1 -> axis2. (This does not include the forces - applied inside the innerZeroThrustRadius for the propeller model. - See below for a description of innerZeroThrustRadius.) - - torque : scalar, float - Torque does not work! If you want swirl, try the simpleProp actType. - The total amount of torque to apply to the region, about the - specified axis. This is only for the uniform actuator zone. - - heat : scalar, float - The total amount of head added in the actuator zone with source terms - - relaxStart : scalar, float - The start of the relaxation in terms of - orders of magnitude of relative convergence - - relaxEnd : scalar, float - The end of the relaxation in terms of - orders of magnitude of relative convergence - - coordXfer : function - A callback function that performs a coordinate transformation - between the original reference frame and any other reference - frame relevant to the current CFD case. This allows user to apply - arbitrary modifications to the loaded plot3d surface. The call - signature is documented in DVGeometry's :meth:`addPointset ` method. - - Note that the following are only for the propeller model. - - swirlFact : scalar - A factor to multiply the tangential forces by. For example, this can - be used to reverse the swirl rotation direction or remove the swirl. - If axis1 -> axis2 points front to back, then a positive swirlFact will - give a clockwise rotation looking from the back. - - mDistribParam : scalar - The m parameter in the distribution. See the Hoekstra or Chauhan and - Martins papers mentioned above. - - nDistribParam : scalar - The n parameter for the distribution. See the Hoekstra or Chauhan and - Martins papers mentioned above. - - distribPDfactor : scalar - The pitch-to-diameter ratio for the blade. See the Hoekstra or - Chauhan and Martins papers mentioned above. Increasing the pitch-to- - diameter ratio increases the swirl. - - innerZeroThrustRadius : scalar - The radius at which the thrust becomes zero and then goes negative. - Only use this if you know the propeller produces drag near the root, - otherwise use the default value of 0. - - propRadius : scalar - The outer radius of the propeller. - - spinnerRadius : scalar - The radius at which the blades connect to the spinner (aka the hub). - - rootDragFactor : scalar - A factor that the negative thrust (drag) inside the innerZeroThrustRadius - is multiplied by. This is used to scale the forces in the region. - This is not required if not using the innerZeroThrustRadius. - """ # ActuatorDiskRegions cannot be used in timeSpectralMode if self.getOption("equationMode").lower() == "time spectral": raise Error("ActuatorRegions cannot be used in Time Spectral Mode.") - # Load in the user supplied surface file. - pts, conn = self._readPlot3DSurfFile(fileName, convertToTris=False, coordXfer=coordXfer) - - # We should do a topology check to ensure that the surface the - # user supplied is actually closed. - # self._closedTopoCheck(pts, conn) # Check if the family name given is already used for something # else. @@ -1042,39 +874,22 @@ def addActuatorRegion( if relaxEnd is None and relaxStart is not None: raise Error("relaxEnd must be given is relaxStart is specified") - if actType != "uniform" and actType != "simpleProp": - raise Error("actType must be 'uniform' or 'simpleProp'") + # tag the correct cells + points, connectivity = actuatorRegion.getEnclosingSurface() + connectivity += 1 # TODO: check if this is right - # Torque input doesn't do anything, warn user if they try to change it - if actType == "uniform" and torque != 0.0 and self.comm.rank == 0: - ADFLOWWarning( - "The torque input does not work for the uniform actuator region. If swirl is desired, try using the simpleProp actuator region." - ) - - # Now continue to fortran were we setup the actual region. self.adflow.actuatorregion.addactuatorregion( - pts.T, - conn.T, - actType, - axis1, - axis2, + points.T, + connectivity.T, familyName, famID, - thrust, - torque, - heat, - swirlFact, - mDistribParam, - nDistribParam, - distribPDfactor, - innerZeroThrustRadius, - propRadius, - spinnerRadius, - rootDragFactor, relaxStart, relaxEnd, ) + # book keep the new region + self.actuatorRegions.append(actuatorRegion) + def writeActuatorRegions(self, fileName, outputDir=None): """ Debug method that writes the cells included in actuator regions diff --git a/src/adjoint/adjointDebug.F90 b/src/adjoint/adjointDebug.F90 index 24119b4d8..ec0f25070 100644 --- a/src/adjoint/adjointDebug.F90 +++ b/src/adjoint/adjointDebug.F90 @@ -559,7 +559,6 @@ subroutine printADSeeds(nn, level, sps) ! And the reverse seeds in the actuator zones do i = 1, nActuatorRegions write (*, *) 'actuatorRegionsd(i)%Force ', actuatorRegionsd(i)%force - write (*, *) 'actuatorRegionsd(i)%Torque ', actuatorRegionsd(i)%torque end do end subroutine printADSeeds diff --git a/src/adjoint/adjointUtils.F90 b/src/adjoint/adjointUtils.F90 index 68dc4d8fe..1d8f80a4c 100644 --- a/src/adjoint/adjointUtils.F90 +++ b/src/adjoint/adjointUtils.F90 @@ -1075,8 +1075,6 @@ subroutine zeroADSeeds(nn, level, sps) ! And the reverse seeds in the actuator zones do i = 1, nActuatorRegions actuatorRegionsd(i)%force = zero - actuatorRegionsd(i)%torque = zero - actuatorRegionsd(i)%thrust = zero actuatorRegionsd(i)%heat = zero actuatorRegionsd(i)%volume = zero end do diff --git a/src/adjoint/outputForward/residuals_d.f90 b/src/adjoint/outputForward/residuals_d.f90 index c8f79ea77..12433b4ca 100644 --- a/src/adjoint/outputForward/residuals_d.f90 +++ b/src/adjoint/outputForward/residuals_d.f90 @@ -341,12 +341,12 @@ end subroutine residual_block ! differentiation of sourceterms_block in forward (tangent) mode (with options i4 dr8 r8): ! variations of useful results: *dw plocal ! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.thrust actuatorregions.heat actuatorregions.volume -! plocal +! actuatorregions.heat actuatorregions.volume actuatorregions.relaxstart +! actuatorregions.relaxend plocal ! rw status of diff variables: uref:in pref:in *w:in *dw:in-out -! *vol:in actuatorregions.force:in actuatorregions.thrust:in -! actuatorregions.heat:in actuatorregions.volume:in -! plocal:in-out +! *vol:in actuatorregions.force:in actuatorregions.heat:in +! actuatorregions.volume:in actuatorregions.relaxstart:in +! actuatorregions.relaxend:in plocal:in-out ! plus diff mem management of: w:in dw:in vol:in subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) ! apply the source terms for the given block. assume that the @@ -357,8 +357,6 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) use flowvarrefstate, only : pref, prefd, uref, urefd, lref use communication use iteration, only : ordersconverged - use diffsizes -! hint: isize1oftemp should be the size of dimension 1 of array temp implicit none ! input integer(kind=inttype), intent(in) :: nn, iregion @@ -370,129 +368,87 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& & , redim, factor, ostart, oend real(kind=realtype) :: ftmpd(3), vxd, vyd, vzd, f_factd(3), q_factd& -& , qtmpd, redimd +& , qtmpd, redimd, factord, ostartd, oendd real(kind=realtype) :: temp - real(kind=realtype) :: temp0 + real(kind=realtype), dimension(3) :: temp0 real(kind=realtype) :: temp1 - real(kind=realtype), dimension(isize1oftemp) :: temp2 - real(kind=realtype), dimension(isize1oftemp) :: temp3 + real(kind=realtype) :: temp2 redimd = uref*prefd + pref*urefd redim = pref*uref ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: if (ordersconverged .lt. actuatorregions(iregion)%relaxstart) then factor = zero + factord = 0.0_8 else if (ordersconverged .gt. actuatorregions(iregion)%relaxend) & & then factor = one + factord = 0.0_8 else ! in between + ostartd = actuatorregionsd(iregion)%relaxstart ostart = actuatorregions(iregion)%relaxstart + oendd = actuatorregionsd(iregion)%relaxend oend = actuatorregions(iregion)%relaxend - factor = (ordersconverged-ostart)/(oend-ostart) + temp = (ordersconverged-ostart)/(oend-ostart) + factord = (-ostartd-temp*(oendd-ostartd))/(oend-ostart) + factor = temp end if -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - temp = actuatorregions(iregion)%volume*pref - f_factd = factor*(actuatorregionsd(iregion)%force-actuatorregions(& -& iregion)%force*(pref*actuatorregionsd(iregion)%volume+& -& actuatorregions(iregion)%volume*prefd)/temp)/temp - f_fact = factor*(actuatorregions(iregion)%force/temp) - else - f_factd = 0.0_8 - end if + temp0 = factor*actuatorregions(iregion)%force/(actuatorregions(& +& iregion)%volume*pref) + f_factd = (actuatorregions(iregion)%force*factord+factor*& +& actuatorregionsd(iregion)%force-temp0*(pref*actuatorregionsd(& +& iregion)%volume+actuatorregions(iregion)%volume*prefd))/(& +& actuatorregions(iregion)%volume*pref) + f_fact = temp0 ! heat factor. this is heat added per unit volume per unit time temp = lref*lref*actuatorregions(iregion)%volume - temp0 = temp*pref*uref - temp1 = actuatorregions(iregion)%heat/temp0 - q_factd = factor*(actuatorregionsd(iregion)%heat-temp1*(pref*uref*& -& lref**2*actuatorregionsd(iregion)%volume+temp*(uref*prefd+pref*& -& urefd)))/temp0 - q_fact = factor*temp1 + temp1 = temp*pref*uref + temp2 = factor*actuatorregions(iregion)%heat/temp1 + q_factd = (actuatorregions(iregion)%heat*factord+factor*& +& actuatorregionsd(iregion)%heat-temp2*(pref*uref*lref**2*& +& actuatorregionsd(iregion)%volume+temp*(uref*prefd+pref*urefd)))/& +& temp1 + q_fact = temp2 ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmpd = f_fact*vold(i, j, k) + vol(i, j, k)*f_factd - ftmp = vol(i, j, k)*f_fact - vxd = wd(i, j, k, ivx) - vx = w(i, j, k, ivx) - vyd = wd(i, j, k, ivy) - vy = w(i, j, k, ivy) - vzd = wd(i, j, k, ivz) - vz = w(i, j, k, ivz) + ftmpd = f_fact*vold(i, j, k) + vol(i, j, k)*f_factd + ftmp = vol(i, j, k)*f_fact + vxd = wd(i, j, k, ivx) + vx = w(i, j, k, ivx) + vyd = wd(i, j, k, ivy) + vy = w(i, j, k, ivy) + vzd = wd(i, j, k, ivz) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmpd = q_fact*vold(i, j, k) + vol(i, j, k)*q_factd - qtmp = vol(i, j, k)*q_fact - if (res) then + qtmpd = q_fact*vold(i, j, k) + vol(i, j, k)*q_factd + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*ftmpd(1) - ftmp& -& (1)*vxd - vy*ftmpd(2) - ftmp(2)*vyd - vz*ftmpd(3) - ftmp(3)*& -& vzd - qtmpd - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - qtmp - else -! add in the local power contribution: - temp1 = vx*ftmp(1) + vy*ftmp(2) + vz*ftmp(3) - plocald = plocald + redim*(ftmp(1)*vxd+vx*ftmpd(1)+ftmp(2)*vyd& -& +vy*ftmpd(2)+ftmp(3)*vzd+vz*ftmpd(3)) + temp1*redimd - plocal = plocal + temp1*redim - end if - end do - end if -! if using the simple propeller force distribution - if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then - do ii=istart,iend -! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) - temp2 = factor*actuatorregions(iregion)%thrustvec(:, ii) - temp1 = actuatorregions(iregion)%thrust/pref - ftmpd = temp2*(actuatorregionsd(iregion)%thrust-temp1*prefd)/& -& pref - ftmp = temp2*temp1 - temp3 = factor*actuatorregions(iregion)%swirlvec(:, ii) - temp1 = actuatorregions(iregion)%thrust/pref - ftmpd = ftmpd + temp3*(actuatorregionsd(iregion)%thrust-temp1*& -& prefd)/pref - ftmp = ftmp + temp3*temp1 - vxd = wd(i, j, k, ivx) - vx = w(i, j, k, ivx) - vyd = wd(i, j, k, ivy) - vy = w(i, j, k, ivy) - vzd = wd(i, j, k, ivz) - vz = w(i, j, k, ivz) - if (res) then -! momentum residuals - dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp -! energy residuals - dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*ftmpd(1) - ftmp& -& (1)*vxd - vy*ftmpd(2) - ftmp(2)*vyd - vz*ftmpd(3) - ftmp(3)*& -& vzd - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - else + dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*ftmpd(1) - ftmp(1& +& )*vxd - vy*ftmpd(2) - ftmp(2)*vyd - vz*ftmpd(3) - ftmp(3)*vzd & +& - qtmpd + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& +& vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - temp1 = vx*ftmp(1) + vy*ftmp(2) + vz*ftmp(3) - plocald = plocald + redim*(ftmp(1)*vxd+vx*ftmpd(1)+ftmp(2)*vyd& -& +vy*ftmpd(2)+ftmp(3)*vzd+vz*ftmpd(3)) + temp1*redimd - plocal = plocal + temp1*redim - end if - end do - end if + temp2 = vx*ftmp(1) + vy*ftmp(2) + vz*ftmp(3) + plocald = plocald + redim*(ftmp(1)*vxd+vx*ftmpd(1)+ftmp(2)*vyd+& +& vy*ftmpd(2)+ftmp(3)*vzd+vz*ftmpd(3)) + temp2*redimd + plocal = plocal + temp2*redim + end if + end do end subroutine sourceterms_block_d subroutine sourceterms_block(nn, res, iregion, plocal) @@ -527,72 +483,39 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref - end if + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then !$ad ii-loop - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact - if (res) then -! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp -! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - qtmp - else -! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do - end if -! if using the simple propeller force distribution - if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then -!$ad ii-loop - do ii=istart,iend -! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) - ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) - if (res) then + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - else + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& +& vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do - end if + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do end subroutine sourceterms_block ! differentiation of initres_block in forward (tangent) mode (with options i4 dr8 r8): diff --git a/src/adjoint/outputReverse/residuals_b.f90 b/src/adjoint/outputReverse/residuals_b.f90 index d800bab56..6291f2641 100644 --- a/src/adjoint/outputReverse/residuals_b.f90 +++ b/src/adjoint/outputReverse/residuals_b.f90 @@ -336,15 +336,15 @@ end subroutine residual_block ! differentiation of sourceterms_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): ! gradient of useful results: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.thrust actuatorregions.heat actuatorregions.volume -! plocal +! actuatorregions.heat actuatorregions.volume actuatorregions.relaxstart +! actuatorregions.relaxend plocal ! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.thrust actuatorregions.heat actuatorregions.volume -! plocal +! actuatorregions.heat actuatorregions.volume actuatorregions.relaxstart +! actuatorregions.relaxend plocal ! rw status of diff variables: uref:incr pref:incr *w:incr *dw:in-out -! *vol:incr actuatorregions.force:incr actuatorregions.thrust:incr -! actuatorregions.heat:incr actuatorregions.volume:incr -! plocal:in-out +! *vol:incr actuatorregions.force:incr actuatorregions.heat:incr +! actuatorregions.volume:incr actuatorregions.relaxstart:incr +! actuatorregions.relaxend:incr plocal:in-out ! plus diff mem management of: w:in dw:in vol:in subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) ! apply the source terms for the given block. assume that the @@ -366,176 +366,115 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& & , redim, factor, ostart, oend real(kind=realtype) :: ftmpd(3), vxd, vyd, vzd, f_factd(3), q_factd& -& , qtmpd, redimd - real(kind=realtype), dimension(3) :: tempd +& , qtmpd, redimd, factord, ostartd, oendd real(kind=realtype) :: temp - real(kind=realtype) :: tempd0 + real(kind=realtype) :: tempd real(kind=realtype) :: temp0 - real(kind=realtype) :: tempd1 + real(kind=realtype) :: tempd0 + real(kind=realtype), dimension(3) :: tempd1 real(kind=realtype) :: tempd2 integer :: branch redim = pref*uref ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: if (ordersconverged .lt. actuatorregions(iregion)%relaxstart) then - call pushcontrol1b(0) + call pushcontrol2b(0) factor = zero else if (ordersconverged .gt. actuatorregions(iregion)%relaxend) & & then - call pushcontrol1b(1) + call pushcontrol2b(1) factor = one else - call pushcontrol1b(1) ! in between ostart = actuatorregions(iregion)%relaxstart oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) + call pushcontrol2b(2) end if -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref - call pushcontrol1b(0) - else - call pushcontrol1b(1) - end if + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then - call pushcontrol1b(0) - else - call pushcontrol1b(1) - end if -! if using the simple propeller force distribution - if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then - redimd = 0.0_8 + q_factd = 0.0_8 + redimd = 0.0_8 + f_factd = 0.0_8 !$bwd-of ii-loop - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) - ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) - if (res) then - ftmpd = 0.0_8 - ftmpd(1) = ftmpd(1) - vx*dwd(i, j, k, irhoe) - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - ftmpd(2) = ftmpd(2) - vy*dwd(i, j, k, irhoe) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - ftmpd(3) = ftmpd(3) - vz*dwd(i, j, k, irhoe) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) - ftmpd = ftmpd - dwd(i, j, k, imx:imz) - else - ftmpd = 0.0_8 - tempd1 = redim*plocald - redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald - vxd = ftmp(1)*tempd1 - ftmpd(1) = ftmpd(1) + vx*tempd1 - vyd = ftmp(2)*tempd1 - ftmpd(2) = ftmpd(2) + vy*tempd1 - vzd = ftmp(3)*tempd1 - ftmpd(3) = ftmpd(3) + vz*tempd1 - end if - wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd - wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd - wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - tempd1 = sum(actuatorregions(iregion)%swirlvec(:, ii)*ftmpd)*& -& factor/pref - actuatorregionsd(iregion)%thrust = actuatorregionsd(iregion)%& -& thrust + tempd1 - prefd = prefd - actuatorregions(iregion)%thrust*tempd1/pref - tempd1 = sum(actuatorregions(iregion)%thrustvec(:, ii)*ftmpd)*& -& factor/pref - actuatorregionsd(iregion)%thrust = actuatorregionsd(iregion)%& -& thrust + tempd1 - prefd = prefd - actuatorregions(iregion)%thrust*tempd1/pref - end do - else - redimd = 0.0_8 - end if - call popcontrol1b(branch) - if (branch .eq. 0) then - q_factd = 0.0_8 - f_factd = 0.0_8 -!$bwd-of ii-loop - do ii=istart,iend -! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - if (res) then - ftmpd = 0.0_8 - ftmpd(1) = ftmpd(1) - vx*dwd(i, j, k, irhoe) - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - ftmpd(2) = ftmpd(2) - vy*dwd(i, j, k, irhoe) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - ftmpd(3) = ftmpd(3) - vz*dwd(i, j, k, irhoe) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) - qtmpd = -dwd(i, j, k, irhoe) - ftmpd = ftmpd - dwd(i, j, k, imx:imz) - else - ftmpd = 0.0_8 - tempd1 = redim*plocald - redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald - vxd = ftmp(1)*tempd1 - ftmpd(1) = ftmpd(1) + vx*tempd1 - vyd = ftmp(2)*tempd1 - ftmpd(2) = ftmpd(2) + vy*tempd1 - vzd = ftmp(3)*tempd1 - ftmpd(3) = ftmpd(3) + vz*tempd1 - qtmpd = 0.0_8 - end if - vold(i, j, k) = vold(i, j, k) + q_fact*qtmpd + sum(f_fact*ftmpd) - q_factd = q_factd + vol(i, j, k)*qtmpd - wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd - wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd - wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - f_factd = f_factd + vol(i, j, k)*ftmpd - end do - else - q_factd = 0.0_8 - f_factd = 0.0_8 - end if - temp = lref*lref*actuatorregions(iregion)%volume - temp0 = temp*pref*uref - tempd1 = factor*q_factd/temp0 + if (res) then + ftmpd = 0.0_8 + ftmpd(1) = ftmpd(1) - vx*dwd(i, j, k, irhoe) + vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) + ftmpd(2) = ftmpd(2) - vy*dwd(i, j, k, irhoe) + vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) + ftmpd(3) = ftmpd(3) - vz*dwd(i, j, k, irhoe) + vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) + qtmpd = -dwd(i, j, k, irhoe) + ftmpd = ftmpd - dwd(i, j, k, imx:imz) + else + ftmpd = 0.0_8 + tempd2 = redim*plocald + redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald + vxd = ftmp(1)*tempd2 + ftmpd(1) = ftmpd(1) + vx*tempd2 + vyd = ftmp(2)*tempd2 + ftmpd(2) = ftmpd(2) + vy*tempd2 + vzd = ftmp(3)*tempd2 + ftmpd(3) = ftmpd(3) + vz*tempd2 + qtmpd = 0.0_8 + end if + vold(i, j, k) = vold(i, j, k) + q_fact*qtmpd + sum(f_fact*ftmpd) + q_factd = q_factd + vol(i, j, k)*qtmpd + wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd + wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd + wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd + f_factd = f_factd + vol(i, j, k)*ftmpd + end do + tempd1 = f_factd/(actuatorregions(iregion)%volume*pref) + tempd0 = -(sum(actuatorregions(iregion)%force*tempd1)*factor/(& +& actuatorregions(iregion)%volume*pref)) + temp0 = lref*lref*actuatorregions(iregion)%volume + temp = temp0*pref*uref + tempd2 = q_factd/temp + factord = actuatorregions(iregion)%heat*tempd2 + sum(actuatorregions& +& (iregion)%force*tempd1) actuatorregionsd(iregion)%heat = actuatorregionsd(iregion)%heat + & -& tempd1 - tempd2 = -(actuatorregions(iregion)%heat*tempd1/temp0) +& factor*tempd2 + tempd = -(factor*actuatorregions(iregion)%heat*tempd2/temp) actuatorregionsd(iregion)%volume = actuatorregionsd(iregion)%volume & -& + lref**2*pref*uref*tempd2 - prefd = prefd + uref*temp*tempd2 - urefd = urefd + pref*temp*tempd2 - call popcontrol1b(branch) - if (branch .eq. 0) then - tempd = factor*f_factd/(actuatorregions(iregion)%volume*pref) - actuatorregionsd(iregion)%force = actuatorregionsd(iregion)%force & -& + tempd - tempd0 = -(sum(actuatorregions(iregion)%force*tempd)/(& -& actuatorregions(iregion)%volume*pref)) - actuatorregionsd(iregion)%volume = actuatorregionsd(iregion)%& -& volume + pref*tempd0 - prefd = prefd + actuatorregions(iregion)%volume*tempd0 +& + lref**2*pref*uref*tempd + pref*tempd0 + prefd = prefd + uref*temp0*tempd + actuatorregions(iregion)%volume*& +& tempd0 + urefd = urefd + pref*temp0*tempd + actuatorregionsd(iregion)%force = actuatorregionsd(iregion)%force + & +& factor*tempd1 + call popcontrol2b(branch) + if (branch .ne. 0) then + if (branch .ne. 1) then + tempd = factord/(oend-ostart) + tempd0 = -((ordersconverged-ostart)*tempd/(oend-ostart)) + ostartd = -tempd - tempd0 + oendd = tempd0 + actuatorregionsd(iregion)%relaxend = actuatorregionsd(iregion)%& +& relaxend + oendd + actuatorregionsd(iregion)%relaxstart = actuatorregionsd(iregion)& +& %relaxstart + ostartd + end if end if - call popcontrol1b(branch) prefd = prefd + uref*redimd urefd = urefd + pref*redimd end subroutine sourceterms_block_b @@ -572,72 +511,39 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref - end if + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then !$ad ii-loop - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact - if (res) then -! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp -! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - qtmp - else -! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do - end if -! if using the simple propeller force distribution - if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then -!$ad ii-loop - do ii=istart,iend -! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) - ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) - if (res) then + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - else + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& +& vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do - end if + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do end subroutine sourceterms_block ! differentiation of initres_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): diff --git a/src/adjoint/outputReverseFast/residuals_fast_b.f90 b/src/adjoint/outputReverseFast/residuals_fast_b.f90 index f57c2745a..edf78f8d1 100644 --- a/src/adjoint/outputReverseFast/residuals_fast_b.f90 +++ b/src/adjoint/outputReverseFast/residuals_fast_b.f90 @@ -378,76 +378,35 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref - end if + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then -myIntPtr = myIntPtr + 1 - myIntStack(myIntPtr) = 0 - else -myIntPtr = myIntPtr + 1 - myIntStack(myIntPtr) = 1 - end if -! if using the simple propeller force distribution - if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then !$bwd-of ii-loop - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) - ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - if (res) then - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) - else - vxd = 0.0_8 - vyd = 0.0_8 - vzd = 0.0_8 - end if - wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd - wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd - wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - end do - end if -branch = myIntStack(myIntPtr) - myIntPtr = myIntPtr - 1 - if (branch .eq. 0) then -!$bwd-of ii-loop - do ii=istart,iend -! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact + ftmp = vol(i, j, k)*f_fact ! this gets the heat addition rate - if (res) then - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) - else - vxd = 0.0_8 - vyd = 0.0_8 - vzd = 0.0_8 - end if - wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd - wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd - wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - end do - end if + if (res) then + vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) + vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) + vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) + else + vxd = 0.0_8 + vyd = 0.0_8 + vzd = 0.0_8 + end if + wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd + wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd + wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd + end do branch = myIntStack(myIntPtr) myIntPtr = myIntPtr - 1 end subroutine sourceterms_block_fast_b @@ -484,72 +443,39 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then ! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref - end if + f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& +& iregion)%volume/pref ! heat factor. this is heat added per unit volume per unit time q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& & iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) -! if using the uniform force distribution - if (actuatorregions(iregion)%acttype .eq. 'uniform') then !$ad ii-loop - do ii=istart,iend + do ii=istart,iend ! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) + i = actuatorregions(iregion)%cellids(1, ii) + j = actuatorregions(iregion)%cellids(2, ii) + k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) + ftmp = vol(i, j, k)*f_fact + vx = w(i, j, k, ivx) + vy = w(i, j, k, ivy) + vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact - if (res) then -! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp -! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - qtmp - else -! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do - end if -! if using the simple propeller force distribution - if (actuatorregions(iregion)%acttype .eq. 'simpleprop') then -!$ad ii-loop - do ii=istart,iend -! extract the cell id. - i = actuatorregions(iregion)%cellids(1, ii) - j = actuatorregions(iregion)%cellids(2, ii) - k = actuatorregions(iregion)%cellids(3, ii) - ftmp = factor*actuatorregions(iregion)%thrustvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - ftmp = ftmp + factor*actuatorregions(iregion)%swirlvec(:, ii)*& -& actuatorregions(iregion)%thrust/pref - vx = w(i, j, k, ivx) - vy = w(i, j, k, ivy) - vz = w(i, j, k, ivz) - if (res) then + qtmp = vol(i, j, k)*q_fact + if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)& -& *vy - ftmp(3)*vz - else + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& +& vy - ftmp(3)*vz - qtmp + else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim - end if - end do - end if + plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + end if + end do end subroutine sourceterms_block ! differentiation of initres_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): diff --git a/src/bcdata/BCData.F90 b/src/bcdata/BCData.F90 index 4ebb6dd75..a6d61ae80 100644 --- a/src/bcdata/BCData.F90 +++ b/src/bcdata/BCData.F90 @@ -1475,26 +1475,26 @@ subroutine setBCData(bcDataNamesIn, bcDataIn, famLists, sps, & end do varLoop end do domainsLoop - ! Loop over any actuator regions since they also could have to set BCData - regionLoop: do iRegion = 1, nActuatorRegions - varLoop2: do iVar = 1, nVar - nFam = famLists(iVar, 1) - famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then - - ! Extract the name - varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) - - if (trim(varName) == "Thrust") then - actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & - bcDataIn(iVar) - else if (trim(varName) == "Torque") then - actuatorRegions(iRegion)%torque = bcDataIn(iVar) - else if (trim(varName) == "Heat") then - actuatorRegions(iRegion)%heat = bcDataIn(iVar) - end if - end if famInclude2 - end do varLoop2 - end do regionLoop + ! ! Loop over any actuator regions since they also could have to set BCData + ! regionLoop: do iRegion = 1, nActuatorRegions + ! varLoop2: do iVar = 1, nVar + ! nFam = famLists(iVar, 1) + ! famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then + + ! ! Extract the name + ! varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) + + ! if (trim(varName) == "Thrust") then + ! actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & + ! bcDataIn(iVar) + ! else if (trim(varName) == "Torque") then + ! actuatorRegions(iRegion)%torque = bcDataIn(iVar) + ! else if (trim(varName) == "Heat") then + ! actuatorRegions(iRegion)%heat = bcDataIn(iVar) + ! end if + ! end if famInclude2 + ! end do varLoop2 + ! end do regionLoop end subroutine setBCData @@ -1573,30 +1573,30 @@ subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & end do varLoop end do domainsLoop - ! Loop over any actuator regions since they also could have to set BCData - regionLoop: do iRegion = 1, nActuatorRegions - varLoop2: do iVar = 1, nVar - nFam = famLists(iVar, 1) - famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then - - ! Extract the name - varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) - - if (trim(varName) == "Thrust") then - actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & - bcDataIn(iVar) - actuatorRegionsd(iRegion)%force = actuatorRegions(iRegion)%axisVec * & - bcDataInd(iVar) - else if (trim(varName) == "Torque") then - actuatorRegions(iRegion)%torque = bcDataIn(iVar) - actuatorRegionsd(iRegion)%torque = bcDataInd(iVar) - else if (trim(varName) == "Heat") then - actuatorRegions(iRegion)%heat = bcDataIn(iVar) - actuatorRegionsd(iRegion)%heat = bcDataInd(iVar) - end if - end if famInclude2 - end do varLoop2 - end do regionLoop + ! ! Loop over any actuator regions since they also could have to set BCData + ! regionLoop: do iRegion = 1, nActuatorRegions + ! varLoop2: do iVar = 1, nVar + ! nFam = famLists(iVar, 1) + ! famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then + + ! ! Extract the name + ! varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) + + ! if (trim(varName) == "Thrust") then + ! actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & + ! bcDataIn(iVar) + ! actuatorRegionsd(iRegion)%force = actuatorRegions(iRegion)%axisVec * & + ! bcDataInd(iVar) + ! else if (trim(varName) == "Torque") then + ! actuatorRegions(iRegion)%torque = bcDataIn(iVar) + ! actuatorRegionsd(iRegion)%torque = bcDataInd(iVar) + ! else if (trim(varName) == "Heat") then + ! actuatorRegions(iRegion)%heat = bcDataIn(iVar) + ! actuatorRegionsd(iRegion)%heat = bcDataInd(iVar) + ! end if + ! end if famInclude2 + ! end do varLoop2 + ! end do regionLoop end subroutine setBCData_d @@ -1678,26 +1678,26 @@ subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & end do varLoop end do domainsLoop - ! Loop over any actuator regions since they also could have to set BCData - regionLoop: do iRegion = 1, nActuatorRegions - varLoop2: do iVar = 1, nVar - nFam = famLists(iVar, 1) - famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then - - ! Extract the name - varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) - - if (trim(varName) == "Thrust") then - bcDataInd(ivar) = & - sum(actuatorRegions(iRegion)%axisVec * actuatorRegionsd(iRegion)%force) - else if (trim(varName) == "Torque") then - bcDataInd(ivar) = actuatorRegionsd(iRegion)%torque - else if (trim(varName) == "Heat") then - bcDataInd(ivar) = actuatorRegionsd(iRegion)%heat - end if - end if famInclude2 - end do varLoop2 - end do regionLoop + ! ! Loop over any actuator regions since they also could have to set BCData + ! regionLoop: do iRegion = 1, nActuatorRegions + ! varLoop2: do iVar = 1, nVar + ! nFam = famLists(iVar, 1) + ! famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then + + ! ! Extract the name + ! varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) + + ! if (trim(varName) == "Thrust") then + ! bcDataInd(ivar) = & + ! sum(actuatorRegions(iRegion)%axisVec * actuatorRegionsd(iRegion)%force) + ! else if (trim(varName) == "Torque") then + ! bcDataInd(ivar) = actuatorRegionsd(iRegion)%torque + ! else if (trim(varName) == "Heat") then + ! bcDataInd(ivar) = actuatorRegionsd(iRegion)%heat + ! end if + ! end if famInclude2 + ! end do varLoop2 + ! end do regionLoop end subroutine setBCData_b diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index 828f55c0f..c45114667 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -685,25 +685,11 @@ python module libadflow end module usersurfaceintegrations module actuatorregion ! in :test:actuatorDiskRegion.F90 - subroutine addactuatorregion(pts,conn,acttype,axis1,axis2,famname,famid,thrust,torque,heat,swirlfact,mdistribparam,ndistribparam,distribpdfactor,innerzerothrustradius,propradius,spinnerradius,rootdragfactor,relaxstart,relaxend,npts,nconn) ! in :test:actuatorDiskRegion.F90:actuatorregion + subroutine addactuatorregion(pts,conn,famname,famid,relaxstart,relaxend,npts,nconn) ! in :test:actuatorDiskRegion.F90:actuatorregion real(kind=realtype) dimension(3,npts),intent(in) :: pts integer(kind=inttype) dimension(4,nconn),intent(in) :: conn - character*(*) :: acttype - real(kind=realtype), dimension(3),intent(in) :: axis1 - real(kind=realtype), dimension(3),intent(in) :: axis2 character*(*) :: famname integer(kind=inttype) intent(in) :: famid - real(kind=realtype) :: thrust - real(kind=realtype) :: torque - real(kind=realtype) :: heat - real(kind=realtype) :: swirlfact - real(kind=realtype) :: mdistribparam - real(kind=realtype) :: ndistribparam - real(kind=realtype) :: distribpdfactor - real(kind=realtype) :: innerzerothrustradius - real(kind=realtype) :: propradius - real(kind=realtype) :: spinnerradius - real(kind=realtype) :: rootdragfactor real(kind=realtype) :: relaxstart real(kind=realtype) :: relaxend integer(kind=inttype), optional,intent(in),check(shape(pts,1)==npts),depend(pts) :: npts=shape(pts,1) diff --git a/src/modules/actuatorRegionData.F90 b/src/modules/actuatorRegionData.F90 index fcf8effb7..af7063fd3 100644 --- a/src/modules/actuatorRegionData.F90 +++ b/src/modules/actuatorRegionData.F90 @@ -3,16 +3,11 @@ module actuatorRegionData type actuatorRegionType - character(len=maxStringLen) :: famName, actType + character(len=maxStringLen) :: famName integer(kind=intType) :: famID ! The block indexes of the cells included in this region integer(kind=intType), dimension(:, :), pointer :: cellIDs - ! The tangent unit-vectors of the cells included in this region - real(kind=realType), dimension(:, :), pointer :: cellTangentials - ! The radii of the cells included in this region - real(kind=realType), dimension(:), pointer :: cellRadii - ! The total number of cells included this proc has integer(kind=intType) :: nCellIDs @@ -20,23 +15,6 @@ module actuatorRegionData ! this is equal to torque * axisVec real(kind=realType) :: force(3) - ! thrust is the total thrust magnitude to be applied on this region - real(kind=realType) :: thrust - real(kind=realType) :: swirlFact - real(kind=realType) :: mDistribParam - real(kind=realType) :: nDistribParam - real(kind=realType) :: distribPDfactor - real(kind=realType) :: innerZeroThrustRadius - real(kind=realType) :: spinnerRadius - real(kind=realType) :: rootDragFactor - - ! magnitude of the total torque to be applied on this region - real(kind=realType) :: torque - ! vector that determines the direction of the applied torque and force - real(kind=realType), dimension(3) :: axisVec - real(kind=realType), dimension(:, :), pointer :: thrustVec - real(kind=realType), dimension(:, :), pointer :: swirlVec - ! total heat flux to be added on this regoin real(kind=realType) :: heat @@ -45,9 +23,6 @@ module actuatorRegionData real(kind=realType) :: volume real(kind=realType) :: volLocal - real(kind=realType) :: totalThrustSum - real(kind=realType) :: totalSwirlSum - integer(kind=intType), dimension(:), allocatable :: blkPtr ! Set the defaults for solution relaxation diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index dc488c35d..2cd1b53ac 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -36,10 +36,7 @@ end subroutine computeActuatorRegionVolume ! ---------------------------------------------------------------------- #ifndef USE_TAPENADE - subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & - thrust, torque, heat, swirlFact, mDistribParam, nDistribParam, & - distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, & - rootDragFactor, relaxStart, relaxEnd, nPts, nConn) + subroutine addActuatorRegion(pts, conn, famName, famID, relaxStart, relaxEnd, nPts, nConn) ! Add a user-supplied integration surface. use communication, only: myID, adflow_comm_world @@ -57,31 +54,25 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & integer(kind=intType), intent(in) :: nPts, nConn, famID real(kind=realType), dimension(3, nPts), intent(in), target :: pts integer(kind=intType), dimension(4, nConn), intent(in), target :: conn - real(kind=realType), intent(in), dimension(3) :: axis1, axis2 - character(len=*) :: famName, actType - real(kind=realType) :: thrust, torque, heat, relaxStart, relaxEnd, swirlFact - real(kind=realType) :: mDistribParam, nDistribParam - real(kind=realType) :: distribPDfactor, innerZeroThrustRadius, propRadius, spinnerRadius, rootDragFactor + character(len=*) :: famName + real(kind=realType) :: relaxStart, relaxEnd ! Working variables integer(kind=intType) :: i, j, k, nn, iDim, cellID, intInfo(3), sps, level, iii, ierr - real(kind=realType) :: dStar, frac, volLocal, dotP + real(kind=realType) :: dStar, volLocal type(actuatorRegionType), pointer :: region - real(kind=realType), dimension(3) :: minX, maxX, v1, v2, v3, xCen, axisVec, radVec + real(kind=realType), dimension(3) :: minX, maxX, v1, v2, v3, xCen type(adtType) :: ADT - real(kind=realType) :: axisVecNorm + ! real(kind=realType) :: axisVecNorm real(kind=realType), dimension(:, :), allocatable :: norm integer(kind=intType), dimension(:), allocatable :: normCount integer(kind=intType), dimension(:, :), pointer :: tmp - real(kind=realType), dimension(:, :), pointer :: tmp2 - real(kind=realType), dimension(:), pointer :: tmp3 - ! ADT Type required data + ! ! ADT Type required data integer(kind=intType), dimension(:), pointer :: frontLeaves, frontLeavesNew type(adtBBoxTargetType), dimension(:), pointer :: BB real(kind=realType) :: coor(4), uvw(5) real(kind=realType) :: dummy(3, 2) - real(kind=realType) :: rHat, fact, fact2, swirlFact2, FTang, Swtmp, thrustSum, Ftmp, swirlSum nActuatorRegions = nActuatorRegions + 1 if (nActuatorRegions > nActuatorRegionsMax) then @@ -92,29 +83,10 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & ! Save the input information region => actuatorRegions(nActuatorRegions) - region%actType = actType region%famName = famName region%famID = famID - region%torque = torque - region%heat = heat region%relaxStart = relaxStart region%relaxEnd = relaxEnd - ! We use the axis to define the direction of F. Since we are - ! dealing with rotating machinary, it is pretty good approximation - ! to assume that the thrust is going to be in the direction of the - ! axis. - axisVec = axis2 - axis1 - axisVecNorm = sqrt((axisVec(1)**2 + axisvec(2)**2 + axisVec(3)**2)) - if (axisVecNorm < 1e-12) then - print *, "Error: Axis cannot be determined by the supplied points. They are too close" - stop - end if - - axisVec = axisVec / axisVecNorm - - region%force = axisVec * thrust - region%thrust = thrust - region%axisVec = axisVec allocate (region%blkPtr(0:nDom)) region%blkPtr(0) = 0 @@ -180,124 +152,50 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & ! Allocate sufficient space for the maximum possible number of cellIDs allocate (region%cellIDs(3, nCellsLocal(1))) - if (region%actType == 'simpleProp') then - ! Allocate sufficient space for the maximum possible number of cellIDs - allocate (region%cellTangentials(3, nCellsLocal(1))) - allocate (region%thrustVec(3, nCellsLocal(1))) - allocate (region%swirlVec(3, nCellsLocal(1))) - - ! Allocate sufficient space for the maximum possible number of cellIDs - allocate (region%cellRadii(nCellsLocal(1))) - region%cellRadii(:) = zero - end if ! Now search for all the coordinate. Note that We have explictly ! set sps to 1 becuase it is only implemented for single grid. sps = 1 level = 1 - thrustSum = zero - swirlSum = zero - do nn = 1, nDom call setPointers(nn, level, sps) do k = 2, kl do j = 2, jl do i = 2, il - ! Only check real cells - if (iblank(i, j, k) == 1) then - ! Compute the cell center - xCen = eighth * (x(i - 1, j - 1, k - 1, :) + x(i, j - 1, k - 1, :) & - + x(i - 1, j, k - 1, :) + x(i, j, k - 1, :) & - + x(i - 1, j - 1, k, :) + x(i, j - 1, k, :) & - + x(i - 1, j, k, :) + x(i, j, k, :)) - - ! The current point to search for and continually - ! reset the "closest point already found" variable. - coor(1:3) = xCen - coor(4) = dStar - intInfo(3) = 0 - call minDistancetreeSearchSinglePoint(ADT, coor, intInfo, & - uvw, dummy, 0, BB, frontLeaves, frontLeavesNew) - cellID = intInfo(3) - if (cellID > 0) then - ! Now check if this was successful or now: - if (checkInside()) then - ! Whoohoo! We are inside the region. Add this cell - ! to the list. - region%nCellIDs = region%nCellIDs + 1 - region%cellIDs(:, region%nCellIDs) = (/i, j, k/) - if (region%actType == 'simpleProp') then - ! Compute cross product for tangential vector and normize - v1 = xCen - axis2 - v2 = axisVec - - v3(1) = (v1(2) * v2(3) - v1(3) * v2(2)) - v3(2) = (v1(3) * v2(1) - v1(1) * v2(3)) - v3(3) = (v1(1) * v2(2) - v1(2) * v2(1)) - v3 = v3 / sqrt(v3(1)**2 + v3(2)**2 + v3(3)**2) - region%cellTangentials(:, region%nCellIDs) = v3 - - ! Compute the dot product and subtract to get radius - dotP = v1(1) * v2(1) + v1(2) * v2(2) + v1(3) * v2(3) - radVec = v1 - dotP * axisVec - region%cellRadii(region%nCellIDs) = & - sqrt(radVec(1)**2 + radVec(2)**2 + radVec(3)**2) - - ! Compute unscaled thrust and swirl forces - if (region%cellRadii(region%nCellIDs) < spinnerRadius) then - - Ftmp = zero - region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec - - Swtmp = zero - region%swirlVec(:, region%nCellIDs) = & - Swtmp * region%cellTangentials(:, region%nCellIDs) - - else if (region%cellRadii(region%nCellIDs) < innerZeroThrustRadius) then - - rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & - / (propRadius - innerZeroThrustRadius)) - fact = rootDragFactor / propRadius - fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & - / (two * pi * region%cellRadii(region%nCellIDs)) - Ftmp = volRef(i, j, k) * fact * fact2 - - thrustSum = thrustSum + Ftmp - - region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec - - Swtmp = zero - region%swirlVec(:, region%nCellIDs) = & - Swtmp * region%cellTangentials(:, region%nCellIDs) - - else - - rHat = ((region%cellRadii(region%nCellIDs) - innerZeroThrustRadius) & - / (propRadius - innerZeroThrustRadius)) - fact = one / propRadius - fact2 = rHat**mDistribParam * (one - rHat)**nDistribParam & - / (two * pi * region%cellRadii(region%nCellIDs)) - Ftmp = volRef(i, j, k) * fact * fact2 - - thrustSum = thrustSum + Ftmp - - region%thrustVec(:, region%nCellIDs) = Ftmp * axisVec - - swirlFact2 = distribPDfactor / pi / region%cellRadii(region%nCellIDs) & - * propRadius * swirlFact - FTang = swirlFact2 * fact * fact2 - Swtmp = volRef(i, j, k) * FTang - - swirlSum = swirlSum + Swtmp - - region%swirlVec(:, region%nCellIDs) = & - Swtmp * region%cellTangentials(:, region%nCellIDs) - end if - end if - end if - end if + ! cycle if it is not a compute cell + if (iblank(i, j, k) /= 1) then + cycle end if + + ! Compute the cell center + xCen = eighth * (x(i - 1, j - 1, k - 1, :) + x(i, j - 1, k - 1, :) & + + x(i - 1, j, k - 1, :) + x(i, j, k - 1, :) & + + x(i - 1, j - 1, k, :) + x(i, j - 1, k, :) & + + x(i - 1, j, k, :) + x(i, j, k, :)) + + ! The current point to search for and continually + ! reset the "closest point already found" variable. + coor(1:3) = xCen + coor(4) = dStar + intInfo(3) = 0 + call minDistancetreeSearchSinglePoint(ADT, coor, intInfo, & + uvw, dummy, 0, BB, frontLeaves, frontLeavesNew) + cellID = intInfo(3) + ! cycle if cell was not found + if (cellID == 0) then + cycle + end if + + ! cycle if cell is not inside actuator region + if (.not. checkInside()) then + cycle + end if + + ! Whoohoo! We are inside the region. Add this cell to the list. + region%nCellIDs = region%nCellIDs + 1 + region%cellIDs(:, region%nCellIDs) = (/i, j, k/) + end do end do end do @@ -308,6 +206,11 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & end do + + ! Now search for all the coordinate. Note that We have explictly + ! set sps to 1 becuase it is only implemented for single grid. + sps = 1 + ! Resize the cellIDs to the correct size now that we know the ! correct exact number. tmp => region%cellIDs @@ -315,37 +218,7 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & region%cellIDs = tmp(:, 1:region%nCellIDs) deallocate (tmp) - if (region%actType == 'simpleProp') then - ! Resize the cellTangentials to the correct size now that we know the - ! correct exact number. - tmp2 => region%cellTangentials - allocate (region%cellTangentials(3, region%nCellIDs)) - region%cellTangentials = tmp2(:, 1:region%nCellIDs) - deallocate (tmp2) - - ! Resize the thrustVec to the correct size now that we know the - ! correct exact number. - tmp2 => region%thrustVec - allocate (region%thrustVec(3, region%nCellIDs)) - region%thrustVec = tmp2(:, 1:region%nCellIDs) - deallocate (tmp2) - - ! Resize the swirlVec to the correct size now that we know the - ! correct exact number. - tmp2 => region%swirlVec - allocate (region%swirlVec(3, region%nCellIDs)) - region%swirlVec = tmp2(:, 1:region%nCellIDs) - deallocate (tmp2) - - ! Resize the cellRadii to the correct size now that we know the - ! correct exact number. - tmp3 => region%cellRadii - allocate (region%cellRadii(region%nCellIDs)) - region%cellRadii = tmp3(1:region%nCellIDs) - deallocate (tmp3) - end if - - ! Now go back and generate the total volume of the the cells we've flagged + ! Now go back and generate the total volume of the cells we've flagged volLocal = zero do nn = 1, nDom @@ -365,25 +238,6 @@ subroutine addActuatorRegion(pts, conn, actType, axis1, axis2, famName, famID, & call ECHK(ierr, __FILE__, __LINE__) write (*, *) "Total vol of actuator region is", region%volume - if (region%actType == 'simpleProp') then - write (*, *) "thrust sum is", thrustSum - call mpi_allreduce(thrustSum, region%totalThrustSum, 1, adflow_real, & - MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - write (*, *) "Total thrust magnitude (mpi sum) without scaling factor is", region%totalThrustSum - - write (*, *) "swirl sum is", swirlSum - call mpi_allreduce(swirlSum, region%totalSwirlSum, 1, adflow_real, & - MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - write (*, *) "Total swirl magnitude (mpi sum) without scaling factor is", region%totalSwirlSum - - region%thrustVec = region%thrustVec / region%totalThrustSum - region%swirlVec = region%swirlVec / region%totalThrustSum - - deallocate (region%cellTangentials) - end if - ! Final memory cleanup deallocate (stack, norm, frontLeaves, frontLeavesNew, BB) call destroySerialQuad(ADT) diff --git a/src/solver/residuals.F90 b/src/solver/residuals.F90 index f869d5ab2..44d8a39a6 100644 --- a/src/solver/residuals.F90 +++ b/src/solver/residuals.F90 @@ -381,11 +381,8 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) factor = (ordersConverged - oStart) / (oEnd - oStart) end if - ! If using the uniform force distribution - if (actuatorRegions(iRegion)%actType == 'uniform') then - ! Compute the constant force factor - F_fact = factor * actuatorRegions(iRegion)%force / actuatorRegions(iRegion)%volume / pRef - end if + ! Compute the constant force factor + F_fact = factor * actuatorRegions(iRegion)%force / actuatorRegions(iRegion)%volume / pRef ! Heat factor. This is heat added per unit volume per unit time Q_fact = factor * actuatorRegions(iRegion)%heat / actuatorRegions(iRegion)%volume / (pRef * uRef * LRef * LRef) @@ -394,70 +391,36 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) iStart = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1 iEnd = actuatorRegions(iRegion)%blkPtr(nn) - ! If using the uniform force distribution - if (actuatorRegions(iRegion)%actType == 'uniform') then - !$AD II-LOOP - do ii = iStart, iEnd - - ! Extract the cell ID. - i = actuatorRegions(iRegion)%cellIDs(1, ii) - j = actuatorRegions(iRegion)%cellIDs(2, ii) - k = actuatorRegions(iRegion)%cellIDs(3, ii) - - ! This actually gets the force - FTmp = vol(i, j, k) * F_fact - - Vx = w(i, j, k, iVx) - Vy = w(i, j, k, iVy) - Vz = w(i, j, k, iVz) - - ! this gets the heat addition rate - QTmp = vol(i, j, k) * Q_fact - - if (res) then - ! Momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp - - ! energy residuals - dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp - else - ! Add in the local power contribution: - pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim - end if - end do - end if + !$AD II-LOOP + do ii = iStart, iEnd - ! If using the simple propeller force distribution - if (actuatorRegions(iRegion)%actType == 'simpleProp') then - !$AD II-LOOP - do ii = iStart, iEnd + ! Extract the cell ID. + i = actuatorRegions(iRegion)%cellIDs(1, ii) + j = actuatorRegions(iRegion)%cellIDs(2, ii) + k = actuatorRegions(iRegion)%cellIDs(3, ii) - ! Extract the cell ID. - i = actuatorRegions(iRegion)%cellIDs(1, ii) - j = actuatorRegions(iRegion)%cellIDs(2, ii) - k = actuatorRegions(iRegion)%cellIDs(3, ii) + ! This actually gets the force + FTmp = vol(i, j, k) * F_fact - Ftmp = factor * actuatorRegions(iRegion)%thrustVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef - Ftmp = Ftmp + factor * actuatorRegions(iRegion)%swirlVec(:, ii) * actuatorRegions(iRegion)%thrust / pRef + Vx = w(i, j, k, iVx) + Vy = w(i, j, k, iVy) + Vz = w(i, j, k, iVz) - Vx = w(i, j, k, iVx) - Vy = w(i, j, k, iVy) - Vz = w(i, j, k, iVz) + ! this gets the heat addition rate + QTmp = vol(i, j, k) * Q_fact - if (res) then - ! Momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp + if (res) then + ! Momentum residuals + dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp - ! energy residuals - dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - else - ! Add in the local power contribution: - pLocal = pLocal + (Vx * Ftmp(1) + Vy * Ftmp(2) + Vz * Ftmp(3)) * reDim - end if - end do - end if + ! energy residuals + dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & + Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp + else + ! Add in the local power contribution: + pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim + end if + end do end subroutine sourceTerms_block From 6933de37d0c393abb7a0f02a47d698f287cd2287 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 6 Jun 2025 15:48:41 +0200 Subject: [PATCH 25/49] move cell tagging logic to python --- adflow/actuatorRegion.py | 289 +++------------------------------- adflow/pyADflow.py | 55 ++----- src/f2py/adflow.pyf | 17 +- src/solver/actuatorRegion.F90 | 245 +++++----------------------- 4 files changed, 91 insertions(+), 515 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 6543be53e..7c34c69ab 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -6,19 +6,25 @@ class AbstractActuatorRegion(ABC): - @abstractmethod - def getEnclosingSurface(self) -> Tuple[npt.NDArray, npt.NDArray]: - points = np.array([[]]) - connectivity = np.array([]) + def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray): + # todo add error checking - return points, connectivity + self.centerPoint = centerPoint + self.thrustVector = thrustVector + + @abstractmethod + def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray) -> npt.NDArray: + flags = np.zeros_like(distance2axis) + return flags class UniformActuatorRegion(AbstractActuatorRegion): - def __init__(self, centerPoint: np.ndarray, thrustVector: np.ndarray, outerDiameter: float, regionDepth: float, thrust: float, heat: float): + def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, outerDiameter: float, regionDepth: float, thrust: float, heat: float): + super().__init__(centerPoint, thrustVector) + if regionDepth <= 0: raise ValueError('"depth" must be greater than 0.') if outerDiameter <= 0: @@ -28,267 +34,22 @@ def __init__(self, centerPoint: np.ndarray, thrustVector: np.ndarray, outerDiame if heat < 0: raise ValueError('"heat" must not be smaller than 0.') - self.centerPoint = centerPoint - self.thrustVector = thrustVector self.outerDiameter = outerDiameter self.regionDepth = regionDepth - def getEnclosingSurface(self): - points = np.array([ - [-3.83050025e-01, -7.20579146E-02, 2.27942117E-01], - [-3.83050025e-01, -7.75741546E-02, 2.63231562E-01], - [-3.83050025e-01, -8.20070252E-02, 3.00000018E-01], - [-3.83050025e-01, -7.75741458E-02, 3.36768473E-01], - [-3.83050025e-01, -7.20578975E-02, 3.72057917E-01], - [-3.83050025e-01, -3.67684649E-02, 2.22425870E-01], - [-3.83050025e-01, -3.95765026E-02, 2.60423519E-01], - [-3.83050025e-01, -4.18330517E-02, 3.00000016E-01], - [-3.83050025e-01, -3.95764964E-02, 3.39576512E-01], - [-3.83050025e-01, -3.67684530E-02, 3.77574161E-01], - [-3.83050025e-01, -3.19709897E-09, 2.17992992E-01], - [-3.83050025e-01, -1.60606457E-09, 2.58166964E-01], - [-3.83050025e-01, 1.25967157E-10, 3.00000014E-01], - [-3.83050025e-01, 1.46254111E-09, 3.41833064E-01], - [-3.83050025e-01, 2.65221633E-09, 3.82007035E-01], - [-3.83050025e-01, 3.67684591E-02, 2.22425867E-01], - [-3.83050025e-01, 3.95764998E-02, 2.60423516E-01], - [-3.83050025e-01, 4.18330521E-02, 3.00000014E-01], - [-3.83050025e-01, 3.95764993E-02, 3.39576511E-01], - [-3.83050025e-01, 3.67684580E-02, 3.77574160E-01], - [-3.83050025e-01, 7.20579095E-02, 2.27942112E-01], - [-3.83050025e-01, 7.75741523E-02, 2.63231557E-01], - [-3.83050025e-01, 8.20070258E-02, 3.00000014E-01], - [-3.83050025e-01, 7.75741486E-02, 3.36768470E-01], - [-3.83050025e-01, 7.20579021E-02, 3.72057916E-01], - [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], - [-3.83050013e-01, -6.77167528E-02, 4.63482739E-01], - [-3.83050013e-01, 5.85581126E-09, 4.77000011E-01], - [-3.83050013e-01, 6.77167636E-02, 4.63482735E-01], - [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], - [-3.83050025e-01, -7.20578975E-02, 3.72057917E-01], - [-3.83050025e-01, -3.67684530E-02, 3.77574161E-01], - [-3.83050025e-01, 2.65221633E-09, 3.82007035E-01], - [-3.83050025e-01, 3.67684580E-02, 3.77574160E-01], - [-3.83050025e-01, 7.20579021E-02, 3.72057916E-01], - [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], - [-3.83050025e-01, 7.20579095E-02, 2.27942112E-01], - [-3.83050013e-01, 1.63482725E-01, 2.32283254E-01], - [-3.83050025e-01, 7.75741523E-02, 2.63231557E-01], - [-3.83050013e-01, 1.77000000E-01, 3.00000015E-01], - [-3.83050025e-01, 8.20070258E-02, 3.00000014E-01], - [-3.83050013e-01, 1.63482724E-01, 3.67716775E-01], - [-3.83050025e-01, 7.75741486E-02, 3.36768470E-01], - [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], - [-3.83050025e-01, 7.20579021E-02, 3.72057916E-01], - [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], - [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], - [-3.83050013e-01, -1.63482733E-01, 2.32283272E-01], - [-2.51800004e-01, -1.63482733E-01, 2.32283272E-01], - [-3.83050013e-01, -1.77000000E-01, 3.00000032E-01], - [-2.51800004e-01, -1.77000000E-01, 3.00000032E-01], - [-3.83050013e-01, -1.63482718E-01, 3.67716789E-01], - [-2.51800004e-01, -1.63482718E-01, 3.67716789E-01], - [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], - [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], - [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], - [-3.83050013e-01, -6.77167795E-02, 1.36517295E-01], - [-3.83050013e-01, -1.15403979E-08, 1.23000013E-01], - [-3.83050013e-01, 6.77167582E-02, 1.36517286E-01], - [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], - [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], - [-2.51800004e-01, -6.77167795E-02, 1.36517295E-01], - [-2.51800004e-01, -1.15403980E-08, 1.23000013E-01], - [-2.51800004e-01, 6.77167582E-02, 1.36517286E-01], - [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], - [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], - [-3.83050013e-01, 1.63482725E-01, 2.32283254E-01], - [-3.83050013e-01, 1.77000000E-01, 3.00000015E-01], - [-3.83050013e-01, 1.63482724E-01, 3.67716775E-01], - [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], - [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], - [-2.51800004e-01, 1.63482725E-01, 2.32283254E-01], - [-2.51800004e-01, 1.77000000E-01, 3.00000015E-01], - [-2.51800004e-01, 1.63482724E-01, 3.67716775E-01], - [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], - [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], - [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], - [-3.83050013e-01, -6.77167528E-02, 4.63482739E-01], - [-2.51800004e-01, -6.77167528E-02, 4.63482739E-01], - [-3.83050013e-01, 5.85581126E-09, 4.77000011E-01], - [-2.51800004e-01, 5.85581115E-09, 4.77000011E-01], - [-3.83050013e-01, 6.77167636E-02, 4.63482735E-01], - [-2.51800004e-01, 6.77167636E-02, 4.63482735E-01], - [-3.83050013e-01, 1.25157899E-01, 4.25157913E-01], - [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], - [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], - [-3.83050025e-01, -7.20579146E-02, 2.27942117E-01], - [-3.83050013e-01, -6.77167795E-02, 1.36517295E-01], - [-3.83050025e-01, -3.67684649E-02, 2.22425870E-01], - [-3.83050013e-01, -1.15403979E-08, 1.23000013E-01], - [-3.83050025e-01, -3.19709897E-09, 2.17992992E-01], - [-3.83050013e-01, 6.77167582E-02, 1.36517286E-01], - [-3.83050025e-01, 3.67684591E-02, 2.22425867E-01], - [-3.83050013e-01, 1.25157903E-01, 1.74842115E-01], - [-3.83050025e-01, 7.20579095E-02, 2.27942112E-01], - [-3.83050013e-01, -1.25157919E-01, 1.74842131E-01], - [-3.83050013e-01, -1.63482733E-01, 2.32283272E-01], - [-3.83050013e-01, -1.77000000E-01, 3.00000032E-01], - [-3.83050013e-01, -1.63482718E-01, 3.67716789E-01], - [-3.83050013e-01, -1.25157891E-01, 4.25157921E-01], - [-3.83050025e-01, -7.20579146E-02, 2.27942117E-01], - [-3.83050025e-01, -7.75741546E-02, 2.63231562E-01], - [-3.83050025e-01, -8.20070252E-02, 3.00000018E-01], - [-3.83050025e-01, -7.75741458E-02, 3.36768473E-01], - [-3.83050025e-01, -7.20578975E-02, 3.72057917E-01], - [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], - [-2.51800001e-01, -7.20579146E-02, 2.27942117E-01], - [-2.51800004e-01, -1.63482733E-01, 2.32283272E-01], - [-2.51800001e-01, -7.75741546E-02, 2.63231562E-01], - [-2.51800004e-01, -1.77000000E-01, 3.00000032E-01], - [-2.51800001e-01, -8.20070252E-02, 3.00000018E-01], - [-2.51800004e-01, -1.63482718E-01, 3.67716789E-01], - [-2.51800001e-01, -7.75741458E-02, 3.36768473E-01], - [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], - [-2.51800001e-01, -7.20578975E-02, 3.72057917E-01], - [-2.51800004e-01, -1.25157891E-01, 4.25157921E-01], - [-2.51800001e-01, -7.20578975E-02, 3.72057917E-01], - [-2.51800004e-01, -6.77167528E-02, 4.63482739E-01], - [-2.51800001e-01, -3.67684530E-02, 3.77574161E-01], - [-2.51800004e-01, 5.85581115E-09, 4.77000011E-01], - [-2.51800001e-01, 2.65221622E-09, 3.82007035E-01], - [-2.51800004e-01, 6.77167636E-02, 4.63482735E-01], - [-2.51800001e-01, 3.67684580E-02, 3.77574160E-01], - [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], - [-2.51800001e-01, 7.20579021E-02, 3.72057916E-01], - [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], - [-2.51800004e-01, 1.63482725E-01, 2.32283254E-01], - [-2.51800004e-01, 1.77000000E-01, 3.00000015E-01], - [-2.51800004e-01, 1.63482724E-01, 3.67716775E-01], - [-2.51800004e-01, 1.25157899E-01, 4.25157913E-01], - [-2.51800001e-01, 7.20579095E-02, 2.27942112E-01], - [-2.51800001e-01, 7.75741523E-02, 2.63231557E-01], - [-2.51800001e-01, 8.20070258E-02, 3.00000014E-01], - [-2.51800001e-01, 7.75741486E-02, 3.36768470E-01], - [-2.51800001e-01, 7.20579021E-02, 3.72057916E-01], - [-2.51800001e-01, -7.20579146E-02, 2.27942117E-01], - [-2.51800001e-01, -3.67684649E-02, 2.22425870E-01], - [-2.51800001e-01, -3.19709907E-09, 2.17992992E-01], - [-2.51800001e-01, 3.67684591E-02, 2.22425867E-01], - [-2.51800001e-01, 7.20579095E-02, 2.27942112E-01], - [-2.51800001e-01, -7.75741546E-02, 2.63231562E-01], - [-2.51800001e-01, -3.95765026E-02, 2.60423519E-01], - [-2.51800001e-01, -1.60606466E-09, 2.58166964E-01], - [-2.51800001e-01, 3.95764998E-02, 2.60423516E-01], - [-2.51800001e-01, 7.75741523E-02, 2.63231557E-01], - [-2.51800001e-01, -8.20070252E-02, 3.00000018E-01], - [-2.51800001e-01, -4.18330517E-02, 3.00000016E-01], - [-2.51800001e-01, 1.25967032E-10, 3.00000014E-01], - [-2.51800001e-01, 4.18330521E-02, 3.00000014E-01], - [-2.51800001e-01, 8.20070258E-02, 3.00000014E-01], - [-2.51800001e-01, -7.75741458E-02, 3.36768473E-01], - [-2.51800001e-01, -3.95764964E-02, 3.39576512E-01], - [-2.51800001e-01, 1.46254098E-09, 3.41833064E-01], - [-2.51800001e-01, 3.95764993E-02, 3.39576511E-01], - [-2.51800001e-01, 7.75741486E-02, 3.36768470E-01], - [-2.51800001e-01, -7.20578975E-02, 3.72057917E-01], - [-2.51800001e-01, -3.67684530E-02, 3.77574161E-01], - [-2.51800001e-01, 2.65221622E-09, 3.82007035E-01], - [-2.51800001e-01, 3.67684580E-02, 3.77574160E-01], - [-2.51800001e-01, 7.20579021E-02, 3.72057916E-01], - [-2.51800004e-01, -1.25157919E-01, 1.74842131E-01], - [-2.51800004e-01, -6.77167795E-02, 1.36517295E-01], - [-2.51800004e-01, -1.15403980E-08, 1.23000013E-01], - [-2.51800004e-01, 6.77167582E-02, 1.36517286E-01], - [-2.51800004e-01, 1.25157903E-01, 1.74842115E-01], - [-2.51800001e-01, -7.20579146E-02, 2.27942117E-01], - [-2.51800001e-01, -3.67684649E-02, 2.22425870E-01], - [-2.51800001e-01, -3.19709907E-09, 2.17992992E-01], - [-2.51800001e-01, 3.67684591E-02, 2.22425867E-01], - [-2.51800001e-01, 7.20579095E-02, 2.27942112E-01], - ]) + def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray) -> npt.NDArray: + flags = np.zeros_like(distance2axis) + + indices = np.logical_and( + distance2axis <= self.outerDiameter/2, + np.logical_and( + distance2plane >= 0, + distance2plane <= self.regionDepth + ) + ) + + flags[indices] = 1 - connectivity = np.array([ - [ 0, 1, 6, 5], - [ 1, 2, 7, 6], - [ 2, 3, 8, 7], - [ 3, 4, 9, 8], - [ 5, 6, 11, 10], - [ 6, 7, 12, 11], - [ 7, 8, 13, 12], - [ 8, 9, 14, 13], - [ 10, 11, 16, 15], - [ 11, 12, 17, 16], - [ 12, 13, 18, 17], - [ 13, 14, 19, 18], - [ 15, 16, 21, 20], - [ 16, 17, 22, 21], - [ 17, 18, 23, 22], - [ 18, 19, 24, 23], - [ 25, 26, 31, 30], - [ 26, 27, 32, 31], - [ 27, 28, 33, 32], - [ 28, 29, 34, 33], - [ 35, 36, 38, 37], - [ 37, 38, 40, 39], - [ 39, 40, 42, 41], - [ 41, 42, 44, 43], - [ 45, 46, 48, 47], - [ 47, 48, 50, 49], - [ 49, 50, 52, 51], - [ 51, 52, 54, 53], - [ 55, 56, 61, 60], - [ 56, 57, 62, 61], - [ 57, 58, 63, 62], - [ 58, 59, 64, 63], - [ 65, 66, 71, 70], - [ 66, 67, 72, 71], - [ 67, 68, 73, 72], - [ 68, 69, 74, 73], - [ 75, 76, 78, 77], - [ 77, 78, 80, 79], - [ 79, 80, 82, 81], - [ 81, 82, 84, 83], - [ 85, 86, 88, 87], - [ 87, 88, 90, 89], - [ 89, 90, 92, 91], - [ 91, 92, 94, 93], - [ 95, 96, 101, 100], - [ 96, 97, 102, 101], - [ 97, 98, 103, 102], - [ 98, 99, 104, 103], - [105, 106, 108, 107], - [107, 108, 110, 109], - [109, 110, 112, 111], - [111, 112, 114, 113], - [115, 116, 118, 117], - [117, 118, 120, 119], - [119, 120, 122, 121], - [121, 122, 124, 123], - [125, 126, 131, 130], - [126, 127, 132, 131], - [127, 128, 133, 132], - [128, 129, 134, 133], - [135, 136, 141, 140], - [136, 137, 142, 141], - [137, 138, 143, 142], - [138, 139, 144, 143], - [140, 141, 146, 145], - [141, 142, 147, 146], - [142, 143, 148, 147], - [143, 144, 149, 148], - [145, 146, 151, 150], - [146, 147, 152, 151], - [147, 148, 153, 152], - [148, 149, 154, 153], - [150, 151, 156, 155], - [151, 152, 157, 156], - [152, 153, 158, 157], - [153, 154, 159, 158], - [160, 161, 166, 165], - [161, 162, 167, 166], - [162, 163, 168, 167], - [163, 164, 169, 168], - ]) + return flags - return points, connectivity diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index c4a9a3493..824838b6b 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -845,48 +845,27 @@ def addActuatorRegion( raise Error("ActuatorRegions cannot be used in Time Spectral Mode.") - # Check if the family name given is already used for something - # else. - if familyName.lower() in self.families: - raise Error( - "Cannot add ActuatorDiskRegion with family name '%s'" "because the name it already exists." % familyName - ) - - # Need to add an additional family so first figure out what - # the max family index is: - maxInd = 0 - for fam in self.families: - if len(self.families[fam]) > 0: - maxInd = max(maxInd, numpy.max(self.families[fam])) - famID = maxInd + 1 - self.families[familyName.lower()] = [famID] + # compute the distance of each cell to the AR plane and axis + ncells = self.adflow.adjointvars.ncellslocal[0] - if relaxStart is None and relaxEnd is None: - # No relaxation at all - relaxStart = -1.0 - relaxEnd = -1.0 - - if relaxStart is None and relaxEnd is not None: - # Start at 0 orders if start is not given - relaxStart = 0.0 - - if relaxEnd is None and relaxStart is not None: - raise Error("relaxEnd must be given is relaxStart is specified") - - # tag the correct cells - points, connectivity = actuatorRegion.getEnclosingSurface() - connectivity += 1 # TODO: check if this is right - - self.adflow.actuatorregion.addactuatorregion( - points.T, - connectivity.T, - familyName, - famID, - relaxStart, - relaxEnd, + distance2plane, distance2axis = self.adflow.actuatorregion.computecelldistances( + actuatorRegion.centerPoint, + actuatorRegion.thrustVector, + ncells ) + # tag the active cells + flags = actuatorRegion.tagActiveCells(distance2axis, distance2plane) + + + print(flags) + + + + # print(distance2axis) + # print(distance2plane) + # book keep the new region self.actuatorRegions.append(actuatorRegion) diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index c45114667..e23e44102 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -685,16 +685,13 @@ python module libadflow end module usersurfaceintegrations module actuatorregion ! in :test:actuatorDiskRegion.F90 - subroutine addactuatorregion(pts,conn,famname,famid,relaxstart,relaxend,npts,nconn) ! in :test:actuatorDiskRegion.F90:actuatorregion - real(kind=realtype) dimension(3,npts),intent(in) :: pts - integer(kind=inttype) dimension(4,nconn),intent(in) :: conn - character*(*) :: famname - integer(kind=inttype) intent(in) :: famid - real(kind=realtype) :: relaxstart - real(kind=realtype) :: relaxend - integer(kind=inttype), optional,intent(in),check(shape(pts,1)==npts),depend(pts) :: npts=shape(pts,1) - integer(kind=inttype), optional,intent(in),check(shape(conn,1)==nconn),depend(conn) :: nconn=shape(conn,1) - end subroutine addactuatorregion + subroutine computecelldistances(centerpoint, thrustvector, n, distance2plane, distance2axis) ! in :test:actuatorDiskRegion.F90:actuatorregion + real(kind=realtype) dimension(3),intent(in) :: centerpoint + real(kind=realtype) dimension(3),intent(in) :: thrustvector + integer(kind=inttype) intent(in) :: n + real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2plane + real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2axis + end subroutine computecelldistances subroutine writeactuatorregions(filename) character*(*) intent(in) :: filename diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 2cd1b53ac..e7a803b09 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -36,133 +36,39 @@ end subroutine computeActuatorRegionVolume ! ---------------------------------------------------------------------- #ifndef USE_TAPENADE - subroutine addActuatorRegion(pts, conn, famName, famID, relaxStart, relaxEnd, nPts, nConn) - ! Add a user-supplied integration surface. + subroutine computeCellDistances(centerPoint, thrustVector, n, distance2plane, distance2axis) - use communication, only: myID, adflow_comm_world use constants - use adtBuild, only: buildSerialQuad, destroySerialQuad - use adtLocalSearch, only: minDistanceTreeSearchSinglePoint - use ADTUtils, only: stack - use ADTData - use blockPointers, only: x, il, jl, kl, nDom, iBlank, vol, volRef - use adjointVars, only: nCellsLocal - use utils, only: setPointers, EChk + use blockPointers, only: x, il, jl, kl, nDom, iBlank + use utils, only: setPointers implicit none ! Input variables - integer(kind=intType), intent(in) :: nPts, nConn, famID - real(kind=realType), dimension(3, nPts), intent(in), target :: pts - integer(kind=intType), dimension(4, nConn), intent(in), target :: conn - character(len=*) :: famName - real(kind=realType) :: relaxStart, relaxEnd - - ! Working variables - integer(kind=intType) :: i, j, k, nn, iDim, cellID, intInfo(3), sps, level, iii, ierr - real(kind=realType) :: dStar, volLocal - type(actuatorRegionType), pointer :: region - real(kind=realType), dimension(3) :: minX, maxX, v1, v2, v3, xCen - type(adtType) :: ADT - ! real(kind=realType) :: axisVecNorm - real(kind=realType), dimension(:, :), allocatable :: norm - integer(kind=intType), dimension(:), allocatable :: normCount - integer(kind=intType), dimension(:, :), pointer :: tmp - - ! ! ADT Type required data - integer(kind=intType), dimension(:), pointer :: frontLeaves, frontLeavesNew - type(adtBBoxTargetType), dimension(:), pointer :: BB - real(kind=realType) :: coor(4), uvw(5) - real(kind=realType) :: dummy(3, 2) - - nActuatorRegions = nActuatorRegions + 1 - if (nActuatorRegions > nActuatorRegionsMax) then - print *, "Error: Exceeded the maximum number of actuatorDiskRegions. "& - &"Increase nActuatorDiskRegionsMax" - stop - end if - - ! Save the input information - region => actuatorRegions(nActuatorRegions) - region%famName = famName - region%famID = famID - region%relaxStart = relaxStart - region%relaxEnd = relaxEnd - - allocate (region%blkPtr(0:nDom)) - region%blkPtr(0) = 0 - - ! Next thing we need to do is to figure out if any of our cells - ! are inside the actuator disk region. If so we will save them in - ! the actuatorRegionType data structure - - ! Since this is effectively a wall-distance calc it gets super - ! costly for the points far away. Luckly, we can do a fairly - ! simple shortcut: Just compute the bounding box of the region and - ! use that as the "already found" distance in the cloest point - ! search. This will eliminate all the points further away - ! immediately and this should be sufficiently fast. - - ! So...compute that bounding box: - do iDim = 1, 3 - minX(iDim) = minval(pts(iDim, :)) - maxX(iDim) = maxval(pts(iDim, :)) - end do - - ! Get the max distance. This should be quite conservative. - dStar = (maxX(1) - minx(1))**2 + (maxX(2) - minX(2))**2 + (maxX(3) - minX(3))**2 - - ! Now build the tree. - call buildSerialQuad(size(conn, 2), size(pts, 2), pts, conn, ADT) - - ! Compute the (averaged) unique nodal vectors: - allocate (norm(3, size(pts, 2)), normCount(size(pts, 2))) - - norm = zero - normCount = 0 - - do i = 1, size(conn, 2) + real(kind=realType), dimension(3), intent(in) :: centerPoint, thrustVector + integer(kind=intType), intent(in) :: n + real(kind=realType), dimension(n), intent(out) :: distance2plane, distance2axis - ! Compute cross product normal and normalize - v1 = pts(:, conn(3, i)) - pts(:, conn(1, i)) - v2 = pts(:, conn(4, i)) - pts(:, conn(2, i)) - v3(1) = (v1(2) * v2(3) - v1(3) * v2(2)) - v3(2) = (v1(3) * v2(1) - v1(1) * v2(3)) - v3(3) = (v1(1) * v2(2) - v1(2) * v2(1)) - v3 = v3 / sqrt(v3(1)**2 + v3(2)**2 + v3(3)**2) - - ! Add to each of the four pts and increment the number added - do j = 1, 4 - norm(:, conn(j, i)) = norm(:, conn(j, i)) + v3 - normCount(conn(j, i)) = normCount(conn(j, i)) + 1 - end do - end do - - ! Now just divide by the norm count - do i = 1, size(pts, 2) - norm(:, i) = norm(:, i) / normCount(i) - end do - - ! Norm count is no longer needed - deallocate (normCount) - - ! Allocate the extra data the tree search requires. - allocate (stack(100), BB(20), frontLeaves(25), frontLeavesNew(25)) - - ! Allocate sufficient space for the maximum possible number of cellIDs - allocate (region%cellIDs(3, nCellsLocal(1))) + ! Working variables + integer(kind=intType) :: ii, i, j, k, nn, iDim, level, sps + real(kind=realType), dimension(3) :: xCen + ! Loop through all the cells and compute the distance of each cell center from the thrust axis (centerPoint + thrustVector) + ! also compute the distance from the plane formed by the centerPoint and the normal trhustVector + distance2axis = large + distance2plane = large - ! Now search for all the coordinate. Note that We have explictly - ! set sps to 1 becuase it is only implemented for single grid. sps = 1 level = 1 + ii = 0 do nn = 1, nDom call setPointers(nn, level, sps) do k = 2, kl do j = 2, jl do i = 2, il + ii = ii + 1 + ! cycle if it is not a compute cell if (iblank(i, j, k) /= 1) then cycle @@ -174,107 +80,40 @@ subroutine addActuatorRegion(pts, conn, famName, famID, relaxStart, relaxEnd, nP + x(i - 1, j - 1, k, :) + x(i, j - 1, k, :) & + x(i - 1, j, k, :) + x(i, j, k, :)) - ! The current point to search for and continually - ! reset the "closest point already found" variable. - coor(1:3) = xCen - coor(4) = dStar - intInfo(3) = 0 - call minDistancetreeSearchSinglePoint(ADT, coor, intInfo, & - uvw, dummy, 0, BB, frontLeaves, frontLeavesNew) - cellID = intInfo(3) - ! cycle if cell was not found - if (cellID == 0) then - cycle - end if - - ! cycle if cell is not inside actuator region - if (.not. checkInside()) then - cycle - end if + ! compute distance from plane + distance2plane(ii) = dot_product(thrustVector, xCen - centerPoint) / vector_norm(thrustVector) - ! Whoohoo! We are inside the region. Add this cell to the list. - region%nCellIDs = region%nCellIDs + 1 - region%cellIDs(:, region%nCellIDs) = (/i, j, k/) + ! Distance from point to axis + distance2axis(ii) = vector_norm(cross_product(xCen - centerPoint, thrustVector)) / vector_norm(thrustVector) end do end do end do - ! Since we're doing all the blocks in order, simply store the - ! current counter into blkPtr which gives up the range of cells - ! we have found on this block - region%blkPtr(nn) = region%nCellIDs - - end do - - - ! Now search for all the coordinate. Note that We have explictly - ! set sps to 1 becuase it is only implemented for single grid. - sps = 1 - - ! Resize the cellIDs to the correct size now that we know the - ! correct exact number. - tmp => region%cellIDs - allocate (region%cellIDs(3, region%nCellIDs)) - region%cellIDs = tmp(:, 1:region%nCellIDs) - deallocate (tmp) - - ! Now go back and generate the total volume of the cells we've flagged - volLocal = zero - - do nn = 1, nDom - call setPointers(nn, level, sps) - - ! Loop over the region for this block - do iii = region%blkPtr(nn - 1) + 1, region%blkPtr(nn) - i = region%cellIDs(1, iii) - j = region%cellIDs(2, iii) - k = region%cellIDs(3, iii) - volLocal = volLocal + vol(i, j, k) - end do end do - call mpi_allreduce(volLocal, region%volume, 1, adflow_real, & - MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - write (*, *) "Total vol of actuator region is", region%volume - - ! Final memory cleanup - deallocate (stack, norm, frontLeaves, frontLeavesNew, BB) - call destroySerialQuad(ADT) contains - - function checkInside() - - implicit none - logical :: checkInside - integer(kind=intType) :: jj - real(kind=realType) :: shp(4), xp(3), normal(3), v1(3), dp - - ! bi-linear shape functions (CCW ordering) - shp(1) = (one - uvw(1)) * (one - uvw(2)) - shp(2) = (uvw(1)) * (one - uvw(2)) - shp(3) = (uvw(1)) * (uvw(2)) - shp(4) = (one - uvw(1)) * (uvw(2)) - - xp = zero - normal = zero - do jj = 1, 4 - xp = xp + shp(jj) * pts(:, conn(jj, cellID)) - normal = normal + shp(jj) * norm(:, conn(jj, cellID)) - end do - - ! Compute the dot product of normal with cell center - ! (stored in coor) with the point on the surface. - v1 = coor(1:3) - xp - dp = normal(1) * v1(1) + normal(2) * v1(2) + normal(3) * v1(3) - - if (dp < zero) then - checkInside = .True. - else - checkInside = .False. - end if - end function checkInside - end subroutine addActuatorRegion + function dot_product(a, b) + real(kind=realType), intent(in) :: a(3), b(3) + real(kind=realType) :: dot_product + dot_product = a(1)*b(1) + a(2)*b(2) + a(3)*b(3) + end function dot_product + + function cross_product(a, b) + real(kind=realType), intent(in) :: a(3), b(3) + real(kind=realType) :: cross_product(3) + + cross_product(1) = a(2)*b(3) - a(3)*b(2) + cross_product(2) = a(3)*b(1) - a(1)*b(3) + cross_product(3) = a(1)*b(2) - a(2)*b(1) + end function cross_product + + function vector_norm(a) + real(kind=realType), intent(in) :: a(3) + real(kind=realType) :: vector_norm + vector_norm = sqrt(a(1)**2 + a(2)**2 + a(3)**2) + end function vector_norm + + end subroutine computeCellDistances subroutine writeActuatorRegions(fileName) From 01fbfa71f11a9c1885c093b6d47d65818acdaa0d Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 6 Jun 2025 17:00:47 +0200 Subject: [PATCH 26/49] finalize cell tagging in fortran --- adflow/pyADflow.py | 45 ++++++++++---- src/f2py/adflow.pyf | 9 +++ src/solver/actuatorRegion.F90 | 112 ++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 11 deletions(-) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 824838b6b..8368aecdd 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -361,7 +361,7 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"): print("| %-30s: %10.3f sec" % ("Total Init Time", finalInitTime - startInitTime)) print("+--------------------------------------------------+") - self.actuatorRegions = list() + self._actuatorRegions = list() def __del__(self): """ @@ -844,6 +844,34 @@ def addActuatorRegion( if self.getOption("equationMode").lower() == "time spectral": raise Error("ActuatorRegions cannot be used in Time Spectral Mode.") + # Check if the family name given is already used for something + # else. + if familyName.lower() in self.families: + raise Error( + "Cannot add ActuatorDiskRegion with family name '%s'" "because the name it already exists." % familyName + ) + + # Need to add an additional family so first figure out what + # the max family index is: + maxInd = 0 + + for fam in self.families: + if len(self.families[fam]) > 0: + maxInd = max(maxInd, numpy.max(self.families[fam])) + famID = maxInd + 1 + self.families[familyName.lower()] = [famID] + + if relaxStart is None and relaxEnd is None: + # No relaxation at all + relaxStart = -1.0 + relaxEnd = -1.0 + + if relaxStart is None and relaxEnd is not None: + # Start at 0 orders if start is not given + relaxStart = 0.0 + + if relaxEnd is None and relaxStart is not None: + raise Error("relaxEnd must be given is relaxStart is specified") # compute the distance of each cell to the AR plane and axis @@ -856,18 +884,13 @@ def addActuatorRegion( ) # tag the active cells - flags = actuatorRegion.tagActiveCells(distance2axis, distance2plane) - - - print(flags) - - - - # print(distance2axis) - # print(distance2plane) + flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane) + self.adflow.actuatorregion.addactuatorregion( + flag, familyName, famID, relaxStart, relaxEnd + ) # book keep the new region - self.actuatorRegions.append(actuatorRegion) + self._actuatorRegions.append(actuatorRegion) def writeActuatorRegions(self, fileName, outputDir=None): """ diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index e23e44102..31ba45878 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -693,6 +693,15 @@ python module libadflow real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2axis end subroutine computecelldistances + subroutine addactuatorregion(flag,n,famname,famid,relaxstart,relaxend) ! in :test:actuatorDiskRegion.F90:actuatorregion + integer(kind=inttype) dimension(n) :: flag + integer(kind=inttype), optional,intent(in),check(len(flag)>=n),depend(flag) :: n=len(flag) + character*(*) :: famname + integer(kind=inttype) intent(in) :: famid + real(kind=realtype) :: relaxstart + real(kind=realtype) :: relaxend + end subroutine addactuatorregion + subroutine writeactuatorregions(filename) character*(*) intent(in) :: filename end subroutine writeactuatorregions diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index e7a803b09..a293e0f6a 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -115,6 +115,118 @@ end function vector_norm end subroutine computeCellDistances + + subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd) + ! Add a user-supplied integration surface. + + use communication, only: myID, adflow_comm_world + use constants + use blockPointers, only: x, il, jl, kl, nDom, iBlank, vol + use adjointVars, only: nCellsLocal + use utils, only: setPointers, EChk + implicit none + + ! Input variables + integer(kind=intType), intent(in) :: famID + character(len=*) :: famName + real(kind=realType) :: relaxStart, relaxEnd + + integer(kind=intType), intent(in) :: n + integer(kind=intType), dimension(n), intent(in) :: flag + + ! Working variables + integer(kind=intType) :: i, j, k, nn, sps, level, ii, iii, ierr + real(kind=realType) :: volLocal + type(actuatorRegionType), pointer :: region + integer(kind=intType), dimension(:, :), pointer :: tmp + + nActuatorRegions = nActuatorRegions + 1 + if (nActuatorRegions > nActuatorRegionsMax) then + print *, "Error: Exceeded the maximum number of actuatorDiskRegions. "& + &"Increase nActuatorDiskRegionsMax" + stop + end if + + ! Save the input information + region => actuatorRegions(nActuatorRegions) + region%famName = famName + region%famID = famID + region%relaxStart = relaxStart + region%relaxEnd = relaxEnd + + + region%force = 0 + region%heat = 0 + + + + allocate (region%blkPtr(0:nDom)) + region%blkPtr(0) = 0 + allocate (region%cellIDs(3, nCellsLocal(1))) + + ! Now search for all the coordinate. Note that We have explictly + ! set sps to 1 becuase it is only implemented for single grid. + sps = 1 + level = 1 + + ii = 0 + do nn = 1, nDom + call setPointers(nn, level, sps) + do k = 2, kl + do j = 2, jl + do i = 2, il + ii = ii + 1 + + ! cycle if it is not a compute cell + if (iblank(i, j, k) /= 1) then + cycle + end if + + ! cycle if cell was not tagged + if (flag(ii) /= 1) then + cycle + end if + + region%nCellIDs = region%nCellIDs + 1 + region%cellIDs(:, region%nCellIDs) = (/i, j, k/) + end do + end do + end do + ! Since we're doing all the blocks in order, simply store the + ! current counter into blkPtr which gives up the range of cells + ! we have found on this block + region%blkPtr(nn) = region%nCellIDs + + end do + + ! Resize the cellIDs to the correct size now that we know the + ! correct exact number. + tmp => region%cellIDs + allocate (region%cellIDs(3, region%nCellIDs)) + region%cellIDs = tmp(:, 1:region%nCellIDs) + deallocate (tmp) + + ! Now go back and generate the total volume of the the cells we've flagged + volLocal = zero + + do nn = 1, nDom + call setPointers(nn, level, sps) + + ! Loop over the region for this block + do iii = region%blkPtr(nn - 1) + 1, region%blkPtr(nn) + i = region%cellIDs(1, iii) + j = region%cellIDs(2, iii) + k = region%cellIDs(3, iii) + volLocal = volLocal + vol(i, j, k) + end do + end do + + call mpi_allreduce(volLocal, region%volume, 1, adflow_real, & + MPI_SUM, adflow_comm_world, ierr) + call ECHK(ierr, __FILE__, __LINE__) + + end subroutine addActuatorRegion + subroutine writeActuatorRegions(fileName) ! This a (mostly) debug routine that is used to verify to the user From 7ada581403ff474ad022d6a491e41aab1902d7b0 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 13 Jun 2025 14:02:44 +0200 Subject: [PATCH 27/49] Streamline spatial cell metrics computation --- adflow/pyADflow.py | 2 +- src/f2py/adflow.pyf | 4 +- src/solver/actuatorRegion.F90 | 80 +++++++++++++++++++---------------- 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 8368aecdd..bb3c808d7 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -877,7 +877,7 @@ def addActuatorRegion( # compute the distance of each cell to the AR plane and axis ncells = self.adflow.adjointvars.ncellslocal[0] - distance2plane, distance2axis = self.adflow.actuatorregion.computecelldistances( + distance2plane, distance2axis = self.adflow.actuatorregion.computeinitialspatialmetrics( actuatorRegion.centerPoint, actuatorRegion.thrustVector, ncells diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index 31ba45878..a67f7bfb4 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -685,13 +685,13 @@ python module libadflow end module usersurfaceintegrations module actuatorregion ! in :test:actuatorDiskRegion.F90 - subroutine computecelldistances(centerpoint, thrustvector, n, distance2plane, distance2axis) ! in :test:actuatorDiskRegion.F90:actuatorregion + subroutine computeinitialspatialmetrics(centerpoint, thrustvector, n, distance2plane, distance2axis) ! in :test:actuatorDiskRegion.F90:actuatorregion real(kind=realtype) dimension(3),intent(in) :: centerpoint real(kind=realtype) dimension(3),intent(in) :: thrustvector integer(kind=inttype) intent(in) :: n real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2plane real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2axis - end subroutine computecelldistances + end subroutine computeinitialspatialmetrics subroutine addactuatorregion(flag,n,famname,famid,relaxstart,relaxend) ! in :test:actuatorDiskRegion.F90:actuatorregion integer(kind=inttype) dimension(n) :: flag diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index a293e0f6a..2e3ecfaa7 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -29,6 +29,47 @@ subroutine computeActuatorRegionVolume(nn, iRegion) end subroutine computeActuatorRegionVolume + + subroutine computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane, distance2axis) + use constants + use blockPointers, only: x + implicit none + + ! Inputs + real(kind=realType), dimension(3), intent(in) :: centerPoint, thrustVector + integer(kind=intType), intent(in) :: i, j, k + + ! Outputs + real(kind=realType), intent(out) :: distance2axis, distance2plane + + ! Working + real(kind=realType) :: thrustVectorNorm, dotProduct, norm + real(kind=realType), dimension(3) :: xCen, distance2center, crossProduct + + ! Compute the cell center + xCen = eighth * (x(i - 1, j - 1, k - 1, :) + x(i, j - 1, k - 1, :) & + + x(i - 1, j, k - 1, :) + x(i, j, k - 1, :) & + + x(i - 1, j - 1, k, :) + x(i, j - 1, k, :) & + + x(i - 1, j, k, :) + x(i, j, k, :)) + + thrustVectorNorm = sqrt(thrustVector(1)**2 + thrustVector(2)**2 + thrustVector(3)**2) + distance2center = xCen - centerPoint + + ! compute distance to plane + dotProduct = thrustVector(1)*distance2center(1) + thrustVector(2)*distance2center(2) + thrustVector(3)*distance2center(3) + distance2plane = dotProduct / thrustVectorNorm + + ! compute distance to axis + crossProduct(1) = distance2center(2)*thrustVector(3) - distance2center(3)*thrustVector(2) + crossProduct(2) = distance2center(3)*thrustVector(1) - distance2center(1)*thrustVector(3) + crossProduct(3) = distance2center(1)*thrustVector(2) - distance2center(2)*thrustVector(1) + + norm = sqrt(crossProduct(1)**2 + crossProduct(2)**2 + crossProduct(3)**2) + + distance2axis = norm / thrustVectorNorm + + end subroutine computeCellSpatialMetrics + ! ---------------------------------------------------------------------- ! | ! No Tapenade Routine below this line | @@ -36,7 +77,7 @@ end subroutine computeActuatorRegionVolume ! ---------------------------------------------------------------------- #ifndef USE_TAPENADE - subroutine computeCellDistances(centerPoint, thrustVector, n, distance2plane, distance2axis) + subroutine computeInitialSpatialMetrics(centerPoint, thrustVector, n, distance2plane, distance2axis) use constants use blockPointers, only: x, il, jl, kl, nDom, iBlank @@ -74,46 +115,13 @@ subroutine computeCellDistances(centerPoint, thrustVector, n, distance2plane, di cycle end if - ! Compute the cell center - xCen = eighth * (x(i - 1, j - 1, k - 1, :) + x(i, j - 1, k - 1, :) & - + x(i - 1, j, k - 1, :) + x(i, j, k - 1, :) & - + x(i - 1, j - 1, k, :) + x(i, j - 1, k, :) & - + x(i - 1, j, k, :) + x(i, j, k, :)) - - ! compute distance from plane - distance2plane(ii) = dot_product(thrustVector, xCen - centerPoint) / vector_norm(thrustVector) - - ! Distance from point to axis - distance2axis(ii) = vector_norm(cross_product(xCen - centerPoint, thrustVector)) / vector_norm(thrustVector) - + call computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane(ii), distance2axis(ii)) end do end do end do end do - contains - function dot_product(a, b) - real(kind=realType), intent(in) :: a(3), b(3) - real(kind=realType) :: dot_product - dot_product = a(1)*b(1) + a(2)*b(2) + a(3)*b(3) - end function dot_product - - function cross_product(a, b) - real(kind=realType), intent(in) :: a(3), b(3) - real(kind=realType) :: cross_product(3) - - cross_product(1) = a(2)*b(3) - a(3)*b(2) - cross_product(2) = a(3)*b(1) - a(1)*b(3) - cross_product(3) = a(1)*b(2) - a(2)*b(1) - end function cross_product - - function vector_norm(a) - real(kind=realType), intent(in) :: a(3) - real(kind=realType) :: vector_norm - vector_norm = sqrt(a(1)**2 + a(2)**2 + a(3)**2) - end function vector_norm - - end subroutine computeCellDistances + end subroutine computeInitialSpatialMetrics subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd) From 45f505301463596e04dacb5e71f5cb11a5fd501b Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Mon, 16 Jun 2025 13:42:23 +0200 Subject: [PATCH 28/49] Save the number of local cells in python after adding it to the fortran side --- adflow/actuatorRegion.py | 14 +++++++++----- adflow/pyADflow.py | 10 ++++++++-- src/f2py/adflow.pyf | 10 ++++++---- src/solver/actuatorRegion.F90 | 16 +++++++++++----- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 7c34c69ab..16161da69 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -11,6 +11,8 @@ def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray): self.centerPoint = centerPoint self.thrustVector = thrustVector + self.iRegion = -1 + self.nLocalCells = -1 @abstractmethod def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray) -> npt.NDArray: @@ -34,18 +36,20 @@ def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, outerDia if heat < 0: raise ValueError('"heat" must not be smaller than 0.') - self.outerDiameter = outerDiameter - self.regionDepth = regionDepth + self._outerDiameter = outerDiameter + self._regionDepth = regionDepth + self._thrust = thrust + self._heat = heat - def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray) -> npt.NDArray: + def tagActiveCells(self, distance2axis, distance2plane): flags = np.zeros_like(distance2axis) indices = np.logical_and( - distance2axis <= self.outerDiameter/2, + distance2axis <= self._outerDiameter/2, np.logical_and( distance2plane >= 0, - distance2plane <= self.regionDepth + distance2plane <= self._regionDepth ) ) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index bb3c808d7..fb8293375 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -885,9 +885,15 @@ def addActuatorRegion( # tag the active cells flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane) - self.adflow.actuatorregion.addactuatorregion( - flag, familyName, famID, relaxStart, relaxEnd + iRegion, nLocalCells = self.adflow.actuatorregion.addactuatorregion( + flag, + familyName, + famID, + relaxStart, + relaxEnd, ) + actuatorRegion.iRegion = iRegion + actuatorRegion.nLocalCells = nLocalCells # book keep the new region self._actuatorRegions.append(actuatorRegion) diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index a67f7bfb4..c84344ff1 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -693,13 +693,15 @@ python module libadflow real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2axis end subroutine computeinitialspatialmetrics - subroutine addactuatorregion(flag,n,famname,famid,relaxstart,relaxend) ! in :test:actuatorDiskRegion.F90:actuatorregion + subroutine addactuatorregion(flag,n,famname,famid,relaxstart,relaxend,iregion,nlocalcells) ! in :test:actuatorDiskRegion.F90:actuatorregion integer(kind=inttype) dimension(n) :: flag integer(kind=inttype), optional,intent(in),check(len(flag)>=n),depend(flag) :: n=len(flag) - character*(*) :: famname + character*(*) intent(in):: famname integer(kind=inttype) intent(in) :: famid - real(kind=realtype) :: relaxstart - real(kind=realtype) :: relaxend + real(kind=realtype) intent(in):: relaxstart + real(kind=realtype) intent(in):: relaxend + integer(kind=inttype), intent(out) :: iregion + integer(kind=inttype), intent(out) :: nlocalcells end subroutine addactuatorregion subroutine writeactuatorregions(filename) diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 2e3ecfaa7..3051b0326 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -124,7 +124,7 @@ subroutine computeInitialSpatialMetrics(centerPoint, thrustVector, n, distance2p end subroutine computeInitialSpatialMetrics - subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd) + subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd, iRegion, nLocalCells) ! Add a user-supplied integration surface. use communication, only: myID, adflow_comm_world @@ -136,12 +136,16 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd) ! Input variables integer(kind=intType), intent(in) :: famID - character(len=*) :: famName - real(kind=realType) :: relaxStart, relaxEnd + character(len=*), intent(in) :: famName + real(kind=realType), intent(in) :: relaxStart, relaxEnd integer(kind=intType), intent(in) :: n integer(kind=intType), dimension(n), intent(in) :: flag + ! Output Variables + integer(kind=intType), intent(out) :: iRegion + integer(kind=intType), intent(out) :: nLocalCells + ! Working variables integer(kind=intType) :: i, j, k, nn, sps, level, ii, iii, ierr real(kind=realType) :: volLocal @@ -157,10 +161,11 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd) ! Save the input information region => actuatorRegions(nActuatorRegions) + iRegion = nActuatorRegions region%famName = famName region%famID = famID - region%relaxStart = relaxStart - region%relaxEnd = relaxEnd + ! region%relaxStart = relaxStart + ! region%relaxEnd = relaxEnd region%force = 0 @@ -213,6 +218,7 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd) allocate (region%cellIDs(3, region%nCellIDs)) region%cellIDs = tmp(:, 1:region%nCellIDs) deallocate (tmp) + nLocalCells = region%nCellIDs ! Now go back and generate the total volume of the the cells we've flagged volLocal = zero From 21d3dfd1325899a51dfbbde8922eeae7e7bf2d89 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Tue, 17 Jun 2025 16:38:41 +0200 Subject: [PATCH 29/49] Prescribe the source terms in python --- adflow/actuatorRegion.py | 27 ++++ adflow/pyADflow.py | 32 +++- src/adjoint/Makefile_tapenade | 3 - src/adjoint/adjointUtils.F90 | 1 - src/adjoint/masterRoutines.F90 | 61 ------- .../outputForward/actuatorRegion_d.f90 | 79 +++++----- src/adjoint/outputForward/residuals_d.f90 | 115 +++++++------- .../outputReverse/actuatorRegion_b.f90 | 73 ++++----- src/adjoint/outputReverse/residuals_b.f90 | 149 ++++++++---------- .../outputReverseFast/residuals_fast_b.f90 | 44 +++--- src/f2py/adflow.pyf | 17 ++ src/modules/actuatorRegionData.F90 | 13 +- src/preprocessing/preprocessingAPI.F90 | 18 --- src/solver/actuatorRegion.F90 | 118 ++++++++------ src/solver/residuals.F90 | 22 ++- 15 files changed, 378 insertions(+), 394 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 16161da69..dbd26e3de 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -19,6 +19,16 @@ def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray flags = np.zeros_like(distance2axis) return flags + @abstractmethod + def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: + force = np.zeros((3, len(distance2axis))) + return force + + @abstractmethod + def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: + heat = np.zeros_like(distance2axis) + return heat + @@ -57,3 +67,20 @@ def tagActiveCells(self, distance2axis, distance2plane): return flags + def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float): + force = np.zeros((len(distance2axis), 3)) + + force[:, :] = np.outer( + self._thrust * cellVolume / totalVolume, + self.thrustVector + ) + + return force + + def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float): + heat = np.zeros_like(distance2axis) + + heat = self._heat * cellVolume / totalVolume + + return heat + diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index fb8293375..7bb258c89 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -203,6 +203,9 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"): # had we read in a param file self.adflow.iteration.deforming_grid = True + + self._actuatorRegions = list() + # In order to properly initialize we need to have mach number # and a few other things set. Just create a dummy aeroproblem, # use it, and then it will be deleted. @@ -361,7 +364,6 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"): print("| %-30s: %10.3f sec" % ("Total Init Time", finalInitTime - startInitTime)) print("+--------------------------------------------------+") - self._actuatorRegions = list() def __del__(self): """ @@ -898,6 +900,32 @@ def addActuatorRegion( # book keep the new region self._actuatorRegions.append(actuatorRegion) + def _updateActuatorRegionsBC(self): + for actuatorRegion in self._actuatorRegions: + + # compute local metrics + distance2plane, distance2axis, volume = self.adflow.actuatorregion.computespatialmetrics( + actuatorRegion.iRegion, + actuatorRegion.nLocalCells, + actuatorRegion.centerPoint, + actuatorRegion.thrustVector, + ) + + totalVolume = self.comm.allreduce(numpy.sum(volume), op=MPI.SUM) + + + # compute the BC + force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, volume, totalVolume) + heat = actuatorRegion.computeCellHeatVector(distance2axis, distance2plane, volume, totalVolume) + + # set the BC value in Fortran + self.adflow.actuatorregion.populatebcvalues( + actuatorRegion.iRegion, + actuatorRegion.nLocalCells, + force.T, + heat.T, + ) + def writeActuatorRegions(self, fileName, outputDir=None): """ Debug method that writes the cells included in actuator regions @@ -3619,6 +3647,8 @@ def _setAeroProblemData(self, aeroProblem, firstCall=False): if not empty: self.adflow.bcdata.setbcdata(nameArray, dataArray, groupArray, 1) + self._updateActuatorRegionsBC() + if not firstCall: self.adflow.initializeflow.updatebcdataalllevels() diff --git a/src/adjoint/Makefile_tapenade b/src/adjoint/Makefile_tapenade index 4042a9fe2..740b99082 100644 --- a/src/adjoint/Makefile_tapenade +++ b/src/adjoint/Makefile_tapenade @@ -104,9 +104,6 @@ bcData%BCDataSubsonicOutflow(bcVarArray, Pref) > \ bcData%BCDataSupersonicInflow(bcVarArray, muRef, rhoRef, Pref, uRef, wInf, pInfCorr) > \ (bcData%rho, bcData%velx, bcData%vely, bcData%velz, bcData%ps, bcData%turbInlet, muRef, rhoRef, Pref, uRef, wInf, pInfCorr) \ \ -actuatorRegion%computeActuatorRegionVolume(vol, actuatorRegions%volLocal) > \ - (vol, actuatorRegions%volLocal)\ -\ adjointExtra%xhalo_block(x) > \ (x) \ \ diff --git a/src/adjoint/adjointUtils.F90 b/src/adjoint/adjointUtils.F90 index 1d8f80a4c..8fb30fa4e 100644 --- a/src/adjoint/adjointUtils.F90 +++ b/src/adjoint/adjointUtils.F90 @@ -1076,7 +1076,6 @@ subroutine zeroADSeeds(nn, level, sps) do i = 1, nActuatorRegions actuatorRegionsd(i)%force = zero actuatorRegionsd(i)%heat = zero - actuatorRegionsd(i)%volume = zero end do end subroutine zeroADSeeds diff --git a/src/adjoint/masterRoutines.F90 b/src/adjoint/masterRoutines.F90 index 050bfbbd2..f0f450fe4 100644 --- a/src/adjoint/masterRoutines.F90 +++ b/src/adjoint/masterRoutines.F90 @@ -39,7 +39,6 @@ subroutine master(useSpatial, famLists, funcValues, forces, & use oversetCommUtilities, only: updateOversetConnectivity use actuatorRegionData, only: nActuatorRegions, actuatorRegions use wallDistanceData, only: xSurfVec, xSurf - use actuatorRegion, only: computeActuatorRegionVolume implicit none @@ -90,13 +89,6 @@ subroutine master(useSpatial, famLists, funcValues, forces, & end do end if - if (useSpatial) then - ! Zero out the local volume pointers for the actuator zone - do iRegion = 1, nActuatorRegions - actuatorRegions(iRegion)%volLocal = zero - end do - end if - do sps = 1, nTimeIntervalsSpectral do nn = 1, nDom call setPointers(nn, 1, sps) @@ -108,11 +100,6 @@ subroutine master(useSpatial, famLists, funcValues, forces, & call volume_block - ! Compute the volume of each actuator region - do iRegion = 1, nActuatorRegions - call computeActuatorRegionVolume(nn, iRegion) - end do - call metric_block call boundaryNormals @@ -143,16 +130,6 @@ subroutine master(useSpatial, famLists, funcValues, forces, & end do end do - ! Sum the local actuator zone volumes into the global actuator - ! zone volumes. - if (useSpatial) then - do iRegion = 1, nActuatorRegions - call mpi_allreduce(actuatorRegions(iRegion)%volLocal, actuatorRegions(iRegion)%volume, 1, & - adflow_real, MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - end do - end if - ! Exchange values call whalo2(currentLevel, 1_intType, nw, .True., .True., .True.) @@ -299,7 +276,6 @@ subroutine master_d(wdot, xdot, forcesDot, dwDot, famLists, funcValues, funcValu use inputOverset, only: oversetUpdateMode use oversetCommUtilities, only: updateOversetConnectivity_d use actuatorRegionData, only: nActuatorRegions, actuatorRegionsd - use actuatorregion_d, only: computeactuatorregionvolume_d #include use petsc implicit none @@ -409,11 +385,6 @@ subroutine master_d(wdot, xdot, forcesDot, dwDot, famLists, funcValues, funcValu call setBCDataFineGrid_d(.true.) end if - ! Zero out the local volume seeds for the actuator zones - do iRegion = 1, nActuatorRegions - actuatorRegionsd(iRegion)%volLocal = zero - end do - do sps = 1, nTimeIntervalsSpectral do nn = 1, nDom @@ -433,11 +404,6 @@ subroutine master_d(wdot, xdot, forcesDot, dwDot, famLists, funcValues, funcValu call volume_block_d() call metric_block_d() - ! Loop over the actuator regions to compute the local - ! volume seeds - do iRegion = 1, nActuatorRegions - call computeActuatorRegionVolume_d(nn, iRegion) - end do call boundaryNormals_d() time = timeunsteadyrestart @@ -481,14 +447,6 @@ subroutine master_d(wdot, xdot, forcesDot, dwDot, famLists, funcValues, funcValu end do end do - ! Loop over the actuator regions again to sum the local volume - ! seeds into the global volume seeds - do iRegion = 1, nActuatorRegions - call mpi_allreduce(actuatorRegionsd(iRegion)%volLocal, actuatorRegionsd(iRegion)%volume, 1, & - adflow_real, MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - end do - ! Just exchange the derivative values. call whalo2_d(1, 1, nw, .True., .True., .True.) @@ -662,7 +620,6 @@ subroutine master_b(wbar, xbar, extraBar, forcesBar, dwBar, nState, famLists, & use oversetCommUtilities, only: updateOversetConnectivity_b use BCRoutines, only: applyAllBC_block use actuatorRegionData, only: nActuatorRegions, actuatorRegionsd - use actuatorregion_b, only: computeactuatorregionvolume_b use monitor, only: timeUnsteadyRestart use section, only: sections, nSections ! used in time-declaration @@ -803,16 +760,6 @@ subroutine master_b(wbar, xbar, extraBar, forcesBar, dwBar, nState, famLists, & end do domainLoop1 end do spsLoop1 - ! All reduce the global AZ volume seeds and store them in the - ! local AZ volume seeds. - ! This is the inverse of the all reduce that is done in forward - ! mode to sum the local seeds into the global seeds. - do iRegion = 1, nActuatorRegions - call mpi_allreduce(actuatorRegionsd(iRegion)%volume, actuatorRegionsd(iRegion)%volLocal, 1, & - adflow_real, mpi_sum, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - end do - ! Need to re-apply the BCs. The reason is that BC halos behind ! interpolated cells need to be recomputed with their new ! interpolated values from actual compute cells. Only needed for @@ -889,9 +836,6 @@ subroutine master_b(wbar, xbar, extraBar, forcesBar, dwBar, nState, famLists, & call gridvelocitiesfinelevel_block_b(useoldcoor, time, sps, nn) call boundaryNormals_b - do iRegion = 1, nActuatorRegions - call computeActuatorRegionVolume_b(nn, iRegion) - end do call metric_block_b call volume_block_b @@ -917,11 +861,6 @@ subroutine master_b(wbar, xbar, extraBar, forcesBar, dwBar, nState, famLists, & end if end do spsLoop2 - ! Zero out the local volume seeds of the actuator zone - do iRegion = 1, nActuatorRegions - actuatorRegionsd(iRegion)%volLocal = zero - end do - if (present(bcDataNames)) then allocate (bcDataValuesdLocal(size(bcDataValuesd))) bcDataValuesdLocal = zero diff --git a/src/adjoint/outputForward/actuatorRegion_d.f90 b/src/adjoint/outputForward/actuatorRegion_d.f90 index 0fd8c8992..b28ff447f 100644 --- a/src/adjoint/outputForward/actuatorRegion_d.f90 +++ b/src/adjoint/outputForward/actuatorRegion_d.f90 @@ -8,52 +8,45 @@ module actuatorregion_d implicit none contains -! differentiation of computeactuatorregionvolume in forward (tangent) mode (with options i4 dr8 r8): -! variations of useful results: actuatorregions.vollocal -! with respect to varying inputs: *vol actuatorregions.vollocal -! rw status of diff variables: *vol:in actuatorregions.vollocal:in-out -! plus diff mem management of: vol:in - subroutine computeactuatorregionvolume_d(nn, iregion) - use blockpointers, only : ndom, vol, vold + subroutine computecellspatialmetrics(i, j, k, centerpoint, & +& thrustvector, distance2plane, distance2axis) + use constants + use blockpointers, only : x implicit none ! inputs - integer(kind=inttype), intent(in) :: nn, iregion + real(kind=realtype), dimension(3), intent(in) :: centerpoint, & +& thrustvector + integer(kind=inttype), intent(in) :: i, j, k +! outputs + real(kind=realtype), intent(out) :: distance2axis, distance2plane ! working - integer(kind=inttype) :: iii - integer(kind=inttype) :: i, j, k -! loop over the region for this block - do iii=actuatorregions(iregion)%blkptr(nn-1)+1,actuatorregions(& -& iregion)%blkptr(nn) - i = actuatorregions(iregion)%cellids(1, iii) - j = actuatorregions(iregion)%cellids(2, iii) - k = actuatorregions(iregion)%cellids(3, iii) -! sum the volume of each cell within the region on this proc - actuatorregionsd(iregion)%vollocal = actuatorregionsd(iregion)%& -& vollocal + vold(i, j, k) - actuatorregions(iregion)%vollocal = actuatorregions(iregion)%& -& vollocal + vol(i, j, k) - end do - end subroutine computeactuatorregionvolume_d - - subroutine computeactuatorregionvolume(nn, iregion) - use blockpointers, only : ndom, vol - implicit none -! inputs - integer(kind=inttype), intent(in) :: nn, iregion -! working - integer(kind=inttype) :: iii - integer(kind=inttype) :: i, j, k -! loop over the region for this block - do iii=actuatorregions(iregion)%blkptr(nn-1)+1,actuatorregions(& -& iregion)%blkptr(nn) - i = actuatorregions(iregion)%cellids(1, iii) - j = actuatorregions(iregion)%cellids(2, iii) - k = actuatorregions(iregion)%cellids(3, iii) -! sum the volume of each cell within the region on this proc - actuatorregions(iregion)%vollocal = actuatorregions(iregion)%& -& vollocal + vol(i, j, k) - end do - end subroutine computeactuatorregionvolume + real(kind=realtype) :: thrustvectornorm, dotproduct, norm + real(kind=realtype), dimension(3) :: xcen, distance2center, & +& crossproduct + intrinsic sqrt + real(kind=realtype) :: arg1 +! compute the cell center + xcen = eighth*(x(i-1, j-1, k-1, :)+x(i, j-1, k-1, :)+x(i-1, j, k-1, & +& :)+x(i, j, k-1, :)+x(i-1, j-1, k, :)+x(i, j-1, k, :)+x(i-1, j, k, & +& :)+x(i, j, k, :)) + arg1 = thrustvector(1)**2 + thrustvector(2)**2 + thrustvector(3)**2 + thrustvectornorm = sqrt(arg1) + distance2center = xcen - centerpoint +! compute distance to plane + dotproduct = thrustvector(1)*distance2center(1) + thrustvector(2)*& +& distance2center(2) + thrustvector(3)*distance2center(3) + distance2plane = dotproduct/thrustvectornorm +! compute distance to axis + crossproduct(1) = distance2center(2)*thrustvector(3) - & +& distance2center(3)*thrustvector(2) + crossproduct(2) = distance2center(3)*thrustvector(1) - & +& distance2center(1)*thrustvector(3) + crossproduct(3) = distance2center(1)*thrustvector(2) - & +& distance2center(2)*thrustvector(1) + arg1 = crossproduct(1)**2 + crossproduct(2)**2 + crossproduct(3)**2 + norm = sqrt(arg1) + distance2axis = norm/thrustvectornorm + end subroutine computecellspatialmetrics ! ---------------------------------------------------------------------- ! | ! no tapenade routine below this line | diff --git a/src/adjoint/outputForward/residuals_d.f90 b/src/adjoint/outputForward/residuals_d.f90 index 12433b4ca..0356bd2c4 100644 --- a/src/adjoint/outputForward/residuals_d.f90 +++ b/src/adjoint/outputForward/residuals_d.f90 @@ -340,14 +340,15 @@ end subroutine residual_block ! differentiation of sourceterms_block in forward (tangent) mode (with options i4 dr8 r8): ! variations of useful results: *dw plocal -! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.heat actuatorregions.volume actuatorregions.relaxstart +! with respect to varying inputs: uref pref *w *dw *(actuatorregions.force) +! *(actuatorregions.heat) actuatorregions.relaxstart ! actuatorregions.relaxend plocal ! rw status of diff variables: uref:in pref:in *w:in *dw:in-out -! *vol:in actuatorregions.force:in actuatorregions.heat:in -! actuatorregions.volume:in actuatorregions.relaxstart:in -! actuatorregions.relaxend:in plocal:in-out -! plus diff mem management of: w:in dw:in vol:in +! *(actuatorregions.force):in *(actuatorregions.heat):in +! actuatorregions.relaxstart:in actuatorregions.relaxend:in +! plocal:in-out +! plus diff mem management of: w:in dw:in actuatorregions.force:in +! actuatorregions.heat:in subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) ! apply the source terms for the given block. assume that the ! block pointers are already set. @@ -365,14 +366,12 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) real(kind=realtype), intent(inout) :: plocald ! working integer(kind=inttype) :: i, j, k, ii, istart, iend - real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& -& , redim, factor, ostart, oend - real(kind=realtype) :: ftmpd(3), vxd, vyd, vzd, f_factd(3), q_factd& -& , qtmpd, redimd, factord, ostartd, oendd + real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & +& ostart, oend + real(kind=realtype) :: vxd, vyd, vzd, fxd, fyd, fzd, qd, redimd, & +& factord, ostartd, oendd real(kind=realtype) :: temp - real(kind=realtype), dimension(3) :: temp0 - real(kind=realtype) :: temp1 - real(kind=realtype) :: temp2 + real(kind=realtype) :: temp0 redimd = uref*prefd + pref*urefd redim = pref*uref ! compute the relaxation factor based on the ordersconverged @@ -394,23 +393,6 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) factord = (-ostartd-temp*(oendd-ostartd))/(oend-ostart) factor = temp end if -! compute the constant force factor - temp0 = factor*actuatorregions(iregion)%force/(actuatorregions(& -& iregion)%volume*pref) - f_factd = (actuatorregions(iregion)%force*factord+factor*& -& actuatorregionsd(iregion)%force-temp0*(pref*actuatorregionsd(& -& iregion)%volume+actuatorregions(iregion)%volume*prefd))/(& -& actuatorregions(iregion)%volume*pref) - f_fact = temp0 -! heat factor. this is heat added per unit volume per unit time - temp = lref*lref*actuatorregions(iregion)%volume - temp1 = temp*pref*uref - temp2 = factor*actuatorregions(iregion)%heat/temp1 - q_factd = (actuatorregions(iregion)%heat*factord+factor*& -& actuatorregionsd(iregion)%heat-temp2*(pref*uref*lref**2*& -& actuatorregionsd(iregion)%volume+temp*(uref*prefd+pref*urefd)))/& -& temp1 - q_fact = temp2 ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) @@ -420,8 +402,18 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmpd = f_fact*vold(i, j, k) + vol(i, j, k)*f_factd - ftmp = vol(i, j, k)*f_fact + temp = factor/pref + fxd = temp*actuatorregionsd(iregion)%force(1, ii) + & +& actuatorregions(iregion)%force(1, ii)*(factord-temp*prefd)/pref + fx = actuatorregions(iregion)%force(1, ii)*temp + temp = factor/pref + fyd = temp*actuatorregionsd(iregion)%force(2, ii) + & +& actuatorregions(iregion)%force(2, ii)*(factord-temp*prefd)/pref + fy = actuatorregions(iregion)%force(2, ii)*temp + temp = factor/pref + fzd = temp*actuatorregionsd(iregion)%force(3, ii) + & +& actuatorregions(iregion)%force(3, ii)*(factord-temp*prefd)/pref + fz = actuatorregions(iregion)%force(3, ii)*temp vxd = wd(i, j, k, ivx) vx = w(i, j, k, ivx) vyd = wd(i, j, k, ivy) @@ -429,24 +421,31 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) vzd = wd(i, j, k, ivz) vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmpd = q_fact*vold(i, j, k) + vol(i, j, k)*q_factd - qtmp = vol(i, j, k)*q_fact + temp = lref*lref*pref*uref + temp0 = factor*actuatorregions(iregion)%heat(ii)/temp + qd = (actuatorregions(iregion)%heat(ii)*factord+factor*& +& actuatorregionsd(iregion)%heat(ii)-temp0*lref**2*(uref*prefd+& +& pref*urefd))/temp + q = temp0 if (res) then ! momentum residuals - dwd(i, j, k, imx:imz) = dwd(i, j, k, imx:imz) - ftmpd - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dwd(i, j, k, imx) = dwd(i, j, k, imx) - fxd + dw(i, j, k, imx) = dw(i, j, k, imx) - fx + dwd(i, j, k, imy) = dwd(i, j, k, imy) - fyd + dw(i, j, k, imy) = dw(i, j, k, imy) - fy + dwd(i, j, k, imz) = dwd(i, j, k, imz) - fzd + dw(i, j, k, imz) = dw(i, j, k, imz) - fz ! energy residuals - dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*ftmpd(1) - ftmp(1& -& )*vxd - vy*ftmpd(2) - ftmp(2)*vyd - vz*ftmpd(3) - ftmp(3)*vzd & -& - qtmpd - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp + dwd(i, j, k, irhoe) = dwd(i, j, k, irhoe) - vx*fxd - fx*vxd - vy& +& *fyd - fy*vyd - vz*fzd - fz*vzd - qd + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - fx*vx - fy*vy - fz*vz & +& - q else ! add in the local power contribution: - temp2 = vx*ftmp(1) + vy*ftmp(2) + vz*ftmp(3) - plocald = plocald + redim*(ftmp(1)*vxd+vx*ftmpd(1)+ftmp(2)*vyd+& -& vy*ftmpd(2)+ftmp(3)*vzd+vz*ftmpd(3)) + temp2*redimd - plocal = plocal + temp2*redim + temp0 = vx*fx + vy*fy + vz*fz + plocald = plocald + redim*(fx*vxd+vx*fxd+fy*vyd+vy*fyd+fz*vzd+vz& +& *fzd) + temp0*redimd + plocal = plocal + temp0*redim end if end do end subroutine sourceterms_block_d @@ -467,8 +466,8 @@ subroutine sourceterms_block(nn, res, iregion, plocal) real(kind=realtype), intent(inout) :: plocal ! working integer(kind=inttype) :: i, j, k, ii, istart, iend - real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& -& , redim, factor, ostart, oend + real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & +& ostart, oend redim = pref*uref ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: @@ -483,12 +482,6 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref -! heat factor. this is heat added per unit volume per unit time - q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& -& iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) @@ -499,21 +492,25 @@ subroutine sourceterms_block(nn, res, iregion, plocal) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact + fx = factor*actuatorregions(iregion)%force(1, ii)/pref + fy = factor*actuatorregions(iregion)%force(2, ii)/pref + fz = factor*actuatorregions(iregion)%force(3, ii)/pref vx = w(i, j, k, ivx) vy = w(i, j, k, ivy) vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact + q = factor*actuatorregions(iregion)%heat(ii)/(pref*uref*lref*lref) if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx) = dw(i, j, k, imx) - fx + dw(i, j, k, imy) = dw(i, j, k, imy) - fy + dw(i, j, k, imz) = dw(i, j, k, imz) - fz ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - fx*vx - fy*vy - fz*vz & +& - q else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + plocal = plocal + (vx*fx+vy*fy+vz*fz)*redim end if end do end subroutine sourceterms_block diff --git a/src/adjoint/outputReverse/actuatorRegion_b.f90 b/src/adjoint/outputReverse/actuatorRegion_b.f90 index 069350fae..b806a34cf 100644 --- a/src/adjoint/outputReverse/actuatorRegion_b.f90 +++ b/src/adjoint/outputReverse/actuatorRegion_b.f90 @@ -8,47 +8,44 @@ module actuatorregion_b implicit none contains -! differentiation of computeactuatorregionvolume in reverse (adjoint) mode (with options noisize i4 dr8 r8): -! gradient of useful results: *vol actuatorregions.vollocal -! with respect to varying inputs: *vol actuatorregions.vollocal -! rw status of diff variables: *vol:incr actuatorregions.vollocal:in-out -! plus diff mem management of: vol:in - subroutine computeactuatorregionvolume_b(nn, iregion) - use blockpointers, only : ndom, vol, vold + subroutine computecellspatialmetrics(i, j, k, centerpoint, & +& thrustvector, distance2plane, distance2axis) + use constants + use blockpointers, only : x implicit none ! inputs - integer(kind=inttype), intent(in) :: nn, iregion + real(kind=realtype), dimension(3), intent(in) :: centerpoint, & +& thrustvector + integer(kind=inttype), intent(in) :: i, j, k +! outputs + real(kind=realtype), intent(out) :: distance2axis, distance2plane ! working - integer(kind=inttype) :: iii - integer(kind=inttype) :: i, j, k - do iii=actuatorregions(iregion)%blkptr(nn),actuatorregions(iregion)%& -& blkptr(nn-1)+1,-1 - i = actuatorregions(iregion)%cellids(1, iii) - j = actuatorregions(iregion)%cellids(2, iii) - k = actuatorregions(iregion)%cellids(3, iii) - vold(i, j, k) = vold(i, j, k) + actuatorregionsd(iregion)%vollocal - end do - end subroutine computeactuatorregionvolume_b - - subroutine computeactuatorregionvolume(nn, iregion) - use blockpointers, only : ndom, vol - implicit none -! inputs - integer(kind=inttype), intent(in) :: nn, iregion -! working - integer(kind=inttype) :: iii - integer(kind=inttype) :: i, j, k -! loop over the region for this block - do iii=actuatorregions(iregion)%blkptr(nn-1)+1,actuatorregions(& -& iregion)%blkptr(nn) - i = actuatorregions(iregion)%cellids(1, iii) - j = actuatorregions(iregion)%cellids(2, iii) - k = actuatorregions(iregion)%cellids(3, iii) -! sum the volume of each cell within the region on this proc - actuatorregions(iregion)%vollocal = actuatorregions(iregion)%& -& vollocal + vol(i, j, k) - end do - end subroutine computeactuatorregionvolume + real(kind=realtype) :: thrustvectornorm, dotproduct, norm + real(kind=realtype), dimension(3) :: xcen, distance2center, & +& crossproduct + intrinsic sqrt +! compute the cell center + xcen = eighth*(x(i-1, j-1, k-1, :)+x(i, j-1, k-1, :)+x(i-1, j, k-1, & +& :)+x(i, j, k-1, :)+x(i-1, j-1, k, :)+x(i, j-1, k, :)+x(i-1, j, k, & +& :)+x(i, j, k, :)) + thrustvectornorm = sqrt(thrustvector(1)**2 + thrustvector(2)**2 + & +& thrustvector(3)**2) + distance2center = xcen - centerpoint +! compute distance to plane + dotproduct = thrustvector(1)*distance2center(1) + thrustvector(2)*& +& distance2center(2) + thrustvector(3)*distance2center(3) + distance2plane = dotproduct/thrustvectornorm +! compute distance to axis + crossproduct(1) = distance2center(2)*thrustvector(3) - & +& distance2center(3)*thrustvector(2) + crossproduct(2) = distance2center(3)*thrustvector(1) - & +& distance2center(1)*thrustvector(3) + crossproduct(3) = distance2center(1)*thrustvector(2) - & +& distance2center(2)*thrustvector(1) + norm = sqrt(crossproduct(1)**2 + crossproduct(2)**2 + crossproduct(3& +& )**2) + distance2axis = norm/thrustvectornorm + end subroutine computecellspatialmetrics ! ---------------------------------------------------------------------- ! | ! no tapenade routine below this line | diff --git a/src/adjoint/outputReverse/residuals_b.f90 b/src/adjoint/outputReverse/residuals_b.f90 index 6291f2641..e9ed7e9bb 100644 --- a/src/adjoint/outputReverse/residuals_b.f90 +++ b/src/adjoint/outputReverse/residuals_b.f90 @@ -335,17 +335,18 @@ subroutine residual_block() end subroutine residual_block ! differentiation of sourceterms_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): -! gradient of useful results: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.heat actuatorregions.volume actuatorregions.relaxstart +! gradient of useful results: uref pref *w *dw *(actuatorregions.force) +! *(actuatorregions.heat) actuatorregions.relaxstart ! actuatorregions.relaxend plocal -! with respect to varying inputs: uref pref *w *dw *vol actuatorregions.force -! actuatorregions.heat actuatorregions.volume actuatorregions.relaxstart +! with respect to varying inputs: uref pref *w *dw *(actuatorregions.force) +! *(actuatorregions.heat) actuatorregions.relaxstart ! actuatorregions.relaxend plocal ! rw status of diff variables: uref:incr pref:incr *w:incr *dw:in-out -! *vol:incr actuatorregions.force:incr actuatorregions.heat:incr -! actuatorregions.volume:incr actuatorregions.relaxstart:incr -! actuatorregions.relaxend:incr plocal:in-out -! plus diff mem management of: w:in dw:in vol:in +! *(actuatorregions.force):incr *(actuatorregions.heat):incr +! actuatorregions.relaxstart:incr actuatorregions.relaxend:incr +! plocal:in-out +! plus diff mem management of: w:in dw:in actuatorregions.force:in +! actuatorregions.heat:in subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) ! apply the source terms for the given block. assume that the ! block pointers are already set. @@ -363,16 +364,14 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) real(kind=realtype), intent(inout) :: plocald ! working integer(kind=inttype) :: i, j, k, ii, istart, iend - real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& -& , redim, factor, ostart, oend - real(kind=realtype) :: ftmpd(3), vxd, vyd, vzd, f_factd(3), q_factd& -& , qtmpd, redimd, factord, ostartd, oendd - real(kind=realtype) :: temp + real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & +& ostart, oend + real(kind=realtype) :: vxd, vyd, vzd, fxd, fyd, fzd, qd, redimd, & +& factord, ostartd, oendd real(kind=realtype) :: tempd - real(kind=realtype) :: temp0 + real(kind=realtype) :: temp real(kind=realtype) :: tempd0 - real(kind=realtype), dimension(3) :: tempd1 - real(kind=realtype) :: tempd2 + real(kind=realtype) :: tempd1 integer :: branch redim = pref*uref ! compute the relaxation factor based on the ordersconverged @@ -391,18 +390,11 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) factor = (ordersconverged-ostart)/(oend-ostart) call pushcontrol2b(2) end if -! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref -! heat factor. this is heat added per unit volume per unit time - q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& -& iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) - q_factd = 0.0_8 redimd = 0.0_8 - f_factd = 0.0_8 + factord = 0.0_8 !$bwd-of ii-loop do ii=istart,iend ! extract the cell id. @@ -410,58 +402,59 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact + fx = factor*actuatorregions(iregion)%force(1, ii)/pref + fy = factor*actuatorregions(iregion)%force(2, ii)/pref + fz = factor*actuatorregions(iregion)%force(3, ii)/pref vx = w(i, j, k, ivx) vy = w(i, j, k, ivy) vz = w(i, j, k, ivz) ! this gets the heat addition rate if (res) then - ftmpd = 0.0_8 - ftmpd(1) = ftmpd(1) - vx*dwd(i, j, k, irhoe) - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - ftmpd(2) = ftmpd(2) - vy*dwd(i, j, k, irhoe) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - ftmpd(3) = ftmpd(3) - vz*dwd(i, j, k, irhoe) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) - qtmpd = -dwd(i, j, k, irhoe) - ftmpd = ftmpd - dwd(i, j, k, imx:imz) + fxd = -(vx*dwd(i, j, k, irhoe)) - dwd(i, j, k, imx) + vxd = -(fx*dwd(i, j, k, irhoe)) + fyd = -(vy*dwd(i, j, k, irhoe)) - dwd(i, j, k, imy) + vyd = -(fy*dwd(i, j, k, irhoe)) + fzd = -(vz*dwd(i, j, k, irhoe)) - dwd(i, j, k, imz) + vzd = -(fz*dwd(i, j, k, irhoe)) + qd = -dwd(i, j, k, irhoe) else - ftmpd = 0.0_8 - tempd2 = redim*plocald - redimd = redimd + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*plocald - vxd = ftmp(1)*tempd2 - ftmpd(1) = ftmpd(1) + vx*tempd2 - vyd = ftmp(2)*tempd2 - ftmpd(2) = ftmpd(2) + vy*tempd2 - vzd = ftmp(3)*tempd2 - ftmpd(3) = ftmpd(3) + vz*tempd2 - qtmpd = 0.0_8 + tempd1 = redim*plocald + redimd = redimd + (vx*fx+vy*fy+vz*fz)*plocald + vxd = fx*tempd1 + fxd = vx*tempd1 + vyd = fy*tempd1 + fyd = vy*tempd1 + vzd = fz*tempd1 + fzd = vz*tempd1 + qd = 0.0_8 end if - vold(i, j, k) = vold(i, j, k) + q_fact*qtmpd + sum(f_fact*ftmpd) - q_factd = q_factd + vol(i, j, k)*qtmpd + tempd0 = actuatorregions(iregion)%force(3, ii)*fzd/pref + temp = lref*lref*pref*uref + tempd = qd/temp + factord = factord + actuatorregions(iregion)%heat(ii)*tempd + & +& tempd0 + actuatorregionsd(iregion)%heat(ii) = actuatorregionsd(iregion)%& +& heat(ii) + factor*tempd + tempd1 = -(lref**2*factor*actuatorregions(iregion)%heat(ii)*tempd/& +& temp) + prefd = prefd + uref*tempd1 - factor*tempd0/pref + urefd = urefd + pref*tempd1 wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd - f_factd = f_factd + vol(i, j, k)*ftmpd + actuatorregionsd(iregion)%force(3, ii) = actuatorregionsd(iregion)& +& %force(3, ii) + factor*fzd/pref + actuatorregionsd(iregion)%force(2, ii) = actuatorregionsd(iregion)& +& %force(2, ii) + factor*fyd/pref + tempd0 = actuatorregions(iregion)%force(2, ii)*fyd/pref + factord = factord + tempd0 + prefd = prefd - factor*tempd0/pref + actuatorregionsd(iregion)%force(1, ii) = actuatorregionsd(iregion)& +& %force(1, ii) + factor*fxd/pref + tempd0 = actuatorregions(iregion)%force(1, ii)*fxd/pref + factord = factord + tempd0 + prefd = prefd - factor*tempd0/pref end do - tempd1 = f_factd/(actuatorregions(iregion)%volume*pref) - tempd0 = -(sum(actuatorregions(iregion)%force*tempd1)*factor/(& -& actuatorregions(iregion)%volume*pref)) - temp0 = lref*lref*actuatorregions(iregion)%volume - temp = temp0*pref*uref - tempd2 = q_factd/temp - factord = actuatorregions(iregion)%heat*tempd2 + sum(actuatorregions& -& (iregion)%force*tempd1) - actuatorregionsd(iregion)%heat = actuatorregionsd(iregion)%heat + & -& factor*tempd2 - tempd = -(factor*actuatorregions(iregion)%heat*tempd2/temp) - actuatorregionsd(iregion)%volume = actuatorregionsd(iregion)%volume & -& + lref**2*pref*uref*tempd + pref*tempd0 - prefd = prefd + uref*temp0*tempd + actuatorregions(iregion)%volume*& -& tempd0 - urefd = urefd + pref*temp0*tempd - actuatorregionsd(iregion)%force = actuatorregionsd(iregion)%force + & -& factor*tempd1 call popcontrol2b(branch) if (branch .ne. 0) then if (branch .ne. 1) then @@ -495,8 +488,8 @@ subroutine sourceterms_block(nn, res, iregion, plocal) real(kind=realtype), intent(inout) :: plocal ! working integer(kind=inttype) :: i, j, k, ii, istart, iend - real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& -& , redim, factor, ostart, oend + real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & +& ostart, oend redim = pref*uref ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: @@ -511,12 +504,6 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref -! heat factor. this is heat added per unit volume per unit time - q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& -& iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) @@ -527,21 +514,25 @@ subroutine sourceterms_block(nn, res, iregion, plocal) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact + fx = factor*actuatorregions(iregion)%force(1, ii)/pref + fy = factor*actuatorregions(iregion)%force(2, ii)/pref + fz = factor*actuatorregions(iregion)%force(3, ii)/pref vx = w(i, j, k, ivx) vy = w(i, j, k, ivy) vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact + q = factor*actuatorregions(iregion)%heat(ii)/(pref*uref*lref*lref) if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx) = dw(i, j, k, imx) - fx + dw(i, j, k, imy) = dw(i, j, k, imy) - fy + dw(i, j, k, imz) = dw(i, j, k, imz) - fz ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - fx*vx - fy*vy - fz*vz & +& - q else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + plocal = plocal + (vx*fx+vy*fy+vz*fz)*redim end if end do end subroutine sourceterms_block diff --git a/src/adjoint/outputReverseFast/residuals_fast_b.f90 b/src/adjoint/outputReverseFast/residuals_fast_b.f90 index edf78f8d1..9b8be42e8 100644 --- a/src/adjoint/outputReverseFast/residuals_fast_b.f90 +++ b/src/adjoint/outputReverseFast/residuals_fast_b.f90 @@ -355,8 +355,8 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) real(kind=realtype), intent(inout) :: plocal ! working integer(kind=inttype) :: i, j, k, ii, istart, iend - real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& -& , redim, factor, ostart, oend + real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & +& ostart, oend real(kind=realtype) :: vxd, vyd, vzd integer :: branch ! compute the relaxation factor based on the ordersconverged @@ -378,10 +378,6 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref -! heat factor. this is heat added per unit volume per unit time ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) @@ -392,12 +388,14 @@ subroutine sourceterms_block_fast_b(nn, res, iregion, plocal) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact + fx = factor*actuatorregions(iregion)%force(1, ii)/pref + fy = factor*actuatorregions(iregion)%force(2, ii)/pref + fz = factor*actuatorregions(iregion)%force(3, ii)/pref ! this gets the heat addition rate if (res) then - vxd = -(ftmp(1)*dwd(i, j, k, irhoe)) - vyd = -(ftmp(2)*dwd(i, j, k, irhoe)) - vzd = -(ftmp(3)*dwd(i, j, k, irhoe)) + vxd = -(fx*dwd(i, j, k, irhoe)) + vyd = -(fy*dwd(i, j, k, irhoe)) + vzd = -(fz*dwd(i, j, k, irhoe)) else vxd = 0.0_8 vyd = 0.0_8 @@ -427,8 +425,8 @@ subroutine sourceterms_block(nn, res, iregion, plocal) real(kind=realtype), intent(inout) :: plocal ! working integer(kind=inttype) :: i, j, k, ii, istart, iend - real(kind=realtype) :: ftmp(3), vx, vy, vz, f_fact(3), q_fact, qtmp& -& , redim, factor, ostart, oend + real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & +& ostart, oend redim = pref*uref ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: @@ -443,12 +441,6 @@ subroutine sourceterms_block(nn, res, iregion, plocal) oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) end if -! compute the constant force factor - f_fact = factor*actuatorregions(iregion)%force/actuatorregions(& -& iregion)%volume/pref -! heat factor. this is heat added per unit volume per unit time - q_fact = factor*actuatorregions(iregion)%heat/actuatorregions(& -& iregion)%volume/(pref*uref*lref*lref) ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) @@ -459,21 +451,25 @@ subroutine sourceterms_block(nn, res, iregion, plocal) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - ftmp = vol(i, j, k)*f_fact + fx = factor*actuatorregions(iregion)%force(1, ii)/pref + fy = factor*actuatorregions(iregion)%force(2, ii)/pref + fz = factor*actuatorregions(iregion)%force(3, ii)/pref vx = w(i, j, k, ivx) vy = w(i, j, k, ivy) vz = w(i, j, k, ivz) ! this gets the heat addition rate - qtmp = vol(i, j, k)*q_fact + q = factor*actuatorregions(iregion)%heat(ii)/(pref*uref*lref*lref) if (res) then ! momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - ftmp + dw(i, j, k, imx) = dw(i, j, k, imx) - fx + dw(i, j, k, imy) = dw(i, j, k, imy) - fy + dw(i, j, k, imz) = dw(i, j, k, imz) - fz ! energy residuals - dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - ftmp(1)*vx - ftmp(2)*& -& vy - ftmp(3)*vz - qtmp + dw(i, j, k, irhoe) = dw(i, j, k, irhoe) - fx*vx - fy*vy - fz*vz & +& - q else ! add in the local power contribution: - plocal = plocal + (vx*ftmp(1)+vy*ftmp(2)+vz*ftmp(3))*redim + plocal = plocal + (vx*fx+vy*fy+vz*fz)*redim end if end do end subroutine sourceterms_block diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index c84344ff1..4d8352a15 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -704,6 +704,23 @@ python module libadflow integer(kind=inttype), intent(out) :: nlocalcells end subroutine addactuatorregion + subroutine computespatialmetrics(iregion, nlocalcells, centerpoint, thrustvector, distance2plane, distance2axis, volume) ! in :test:actuatorDiskRegion.F90:actuatorregion + real(kind=realtype) dimension(3),intent(in) :: centerpoint + real(kind=realtype) dimension(3),intent(in) :: thrustvector + integer(kind=inttype), intent(in) :: iregion + integer(kind=inttype) intent(in) :: nlocalcells + real(kind=realtype) dimension(nlocalcells),intent(out),depend(nlocalcells) :: distance2plane + real(kind=realtype) dimension(nlocalcells),intent(out),depend(nlocalcells) :: distance2axis + real(kind=realtype) dimension(nlocalcells),intent(out),depend(nlocalcells) :: volume + end subroutine addactuatorregion + + subroutine populatebcvalues(iregion, nlocalcells, force, heat) ! in :test:actuatorDiskRegion.F90:actuatorregion + integer(kind=inttype), intent(in) :: iregion + integer(kind=inttype) intent(in) :: nlocalcells + real(kind=realtype) dimension(3, nlocalcells),intent(in),depend(nlocalcells) :: force + real(kind=realtype) dimension(nlocalcells),intent(in),depend(nlocalcells) :: heat + end subroutine populatebcvalues + subroutine writeactuatorregions(filename) character*(*) intent(in) :: filename end subroutine writeactuatorregions diff --git a/src/modules/actuatorRegionData.F90 b/src/modules/actuatorRegionData.F90 index af7063fd3..ffb811e79 100644 --- a/src/modules/actuatorRegionData.F90 +++ b/src/modules/actuatorRegionData.F90 @@ -11,17 +11,8 @@ module actuatorRegionData ! The total number of cells included this proc has integer(kind=intType) :: nCellIDs - ! the force vector to be applied on this region - ! this is equal to torque * axisVec - real(kind=realType) :: force(3) - - ! total heat flux to be added on this regoin - real(kind=realType) :: heat - - ! Volume is the total integrated volume of all cells (on all - ! procs) included in this region - real(kind=realType) :: volume - real(kind=realType) :: volLocal + real(kind=realType), dimension(:, :), pointer :: force + real(kind=realType), dimension(:), pointer :: heat integer(kind=intType), dimension(:), allocatable :: blkPtr diff --git a/src/preprocessing/preprocessingAPI.F90 b/src/preprocessing/preprocessingAPI.F90 index 6516357ec..9991634ef 100644 --- a/src/preprocessing/preprocessingAPI.F90 +++ b/src/preprocessing/preprocessingAPI.F90 @@ -2732,7 +2732,6 @@ subroutine metric(level) use communication use inputTimeSpectral use checkVolBlock - use actuatorRegion, only: computeActuatorRegionVolume use actuatorRegionData, only: nActuatorRegions, actuatorRegions use inputIteration, only: printWarnings, printNegativeVolumes, & useSkewnessCheck, meshMaxSkewness, printBadlySkewedCells @@ -2787,11 +2786,6 @@ subroutine metric(level) nBlockBad = 0 nBadSkew = 0 - ! Zero out the local volume pointers for the actuator zone - do iRegion = 1, nActuatorRegions - actuatorRegions(iRegion)%volLocal = zero - end do - ! Loop over the number of spectral solutions and local blocks. spectral: do sps = 1, nTimeIntervalsSpectral @@ -3063,11 +3057,6 @@ subroutine metric(level) end do end do - ! Compute the volume of the actuator regions on each domain - do iRegion = 1, nActuatorRegions - call computeActuatorRegionVolume(nn, iRegion) - end do - ! Determine the orientation of the block. For the fine level ! this is based on the number of positive and negative ! volumes; on the coarse levels the corresponding fine level @@ -3347,13 +3336,6 @@ subroutine metric(level) end do domains end do spectral - ! Loop over the actuator regions again to compute the total volumes - do iRegion = 1, nActuatorRegions - call mpi_allreduce(actuatorRegions(iRegion)%volLocal, actuatorRegions(iRegion)%volume, 1, & - adflow_real, mpi_sum, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) - end do - ! Determine the global number of bad blocks. The result must be ! known on all processors and thus an allreduce is needed. diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 3051b0326..72c582c8e 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -6,30 +6,6 @@ module actuatorRegion implicit none contains - subroutine computeActuatorRegionVolume(nn, iRegion) - use blockPointers, only: nDom, vol - implicit none - - ! Inputs - integer(kind=intType), intent(in) :: nn, iRegion - - ! Working - integer(kind=intType) :: iii - integer(kind=intType) :: i, j, k - - ! Loop over the region for this block - do iii = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1, actuatorRegions(iRegion)%blkPtr(nn) - i = actuatorRegions(iRegion)%cellIDs(1, iii) - j = actuatorRegions(iRegion)%cellIDs(2, iii) - k = actuatorRegions(iRegion)%cellIDs(3, iii) - - ! Sum the volume of each cell within the region on this proc - actuatorRegions(iRegion)%volLocal = actuatorRegions(iRegion)%volLocal + vol(i, j, k) - end do - - end subroutine computeActuatorRegionVolume - - subroutine computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane, distance2axis) use constants use blockPointers, only: x @@ -70,6 +46,7 @@ subroutine computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distanc end subroutine computeCellSpatialMetrics + ! ---------------------------------------------------------------------- ! | ! No Tapenade Routine below this line | @@ -148,7 +125,6 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd, iReg ! Working variables integer(kind=intType) :: i, j, k, nn, sps, level, ii, iii, ierr - real(kind=realType) :: volLocal type(actuatorRegionType), pointer :: region integer(kind=intType), dimension(:, :), pointer :: tmp @@ -164,13 +140,8 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd, iReg iRegion = nActuatorRegions region%famName = famName region%famID = famID - ! region%relaxStart = relaxStart - ! region%relaxEnd = relaxEnd - - - region%force = 0 - region%heat = 0 - + region%relaxStart = relaxStart + region%relaxEnd = relaxEnd allocate (region%blkPtr(0:nDom)) @@ -212,6 +183,7 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd, iReg end do + ! Resize the cellIDs to the correct size now that we know the ! correct exact number. tmp => region%cellIDs @@ -220,26 +192,84 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd, iReg deallocate (tmp) nLocalCells = region%nCellIDs - ! Now go back and generate the total volume of the the cells we've flagged - volLocal = zero + ! Allocate variables for the source terms + allocate (region%force(3, region%nCellIDs)) + allocate (region%heat(region%nCellIDs)) + + end subroutine addActuatorRegion + + subroutine computeSpatialMetrics(iRegion, nLocalCells, centerPoint, thrustVector, distance2plane, distance2axis, volume) + use constants + use blockPointers, only: nDom, vol + use utils, only: setPointers + implicit none + + ! Inputs + real(kind=realType), dimension(3), intent(in) :: centerPoint, thrustVector + integer(kind=intType), intent(in) :: nLocalCells + integer(kind=intType), intent(in) :: iRegion + + ! Outputs + real(kind=realType), intent(out), dimension(nLocalCells) :: distance2axis, distance2plane, volume + + ! Working + type(actuatorRegionType), pointer :: region + integer(kind=intType) :: sps, level, nn, i, j, k, iii + + region => actuatorRegions(iRegion) + + + sps = 1 + level = 1 do nn = 1, nDom call setPointers(nn, level, sps) + do iii = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1, actuatorRegions(iRegion)%blkPtr(nn) + i = actuatorRegions(iRegion)%cellIDs(1, iii) + j = actuatorRegions(iRegion)%cellIDs(2, iii) + k = actuatorRegions(iRegion)%cellIDs(3, iii) + - ! Loop over the region for this block - do iii = region%blkPtr(nn - 1) + 1, region%blkPtr(nn) - i = region%cellIDs(1, iii) - j = region%cellIDs(2, iii) - k = region%cellIDs(3, iii) - volLocal = volLocal + vol(i, j, k) + call computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane(iii), distance2axis(iii)) + volume(iii) = vol(i, j, k) end do end do - call mpi_allreduce(volLocal, region%volume, 1, adflow_real, & - MPI_SUM, adflow_comm_world, ierr) - call ECHK(ierr, __FILE__, __LINE__) + end subroutine computeSpatialMetrics + + subroutine populateBCValues(iRegion, nLocalCells, force, heat) + use constants + use blockPointers, only: nDom + use utils, only: setPointers + implicit none + + ! Inputs + integer(kind=intType), intent(in) :: iRegion + integer(kind=intType), intent(in) :: nLocalCells + real(kind=realType), dimension(3, nLocalCells), intent(in) :: force + real(kind=realType), dimension(nLocalCells), intent(in) :: heat + + + ! Working + type(actuatorRegionType), pointer :: region + integer(kind=intType) :: sps, level, nn, i, j, k, iii + + + region => actuatorRegions(iRegion) + + + sps = 1 + level = 1 + do nn = 1, nDom + call setPointers(nn, level, sps) + do iii = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1, actuatorRegions(iRegion)%blkPtr(nn) + actuatorRegions(iRegion)%force(:, iii) = force(:, iii) + actuatorRegions(iRegion)%heat(iii) = heat(iii) + end do + end do + + end subroutine populateBCValues - end subroutine addActuatorRegion subroutine writeActuatorRegions(fileName) diff --git a/src/solver/residuals.F90 b/src/solver/residuals.F90 index 44d8a39a6..9e7dcc7ed 100644 --- a/src/solver/residuals.F90 +++ b/src/solver/residuals.F90 @@ -364,7 +364,7 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) ! Working integer(kind=intType) :: i, j, k, ii, iStart, iEnd - real(kind=realType) :: Ftmp(3), Vx, Vy, Vz, F_fact(3), Q_fact, Qtmp, reDim, factor, oStart, oEnd + real(kind=realType) :: Vx, Vy, Vz, Fx, Fy, Fz, Q, reDim, factor, oStart, oEnd reDim = pRef * uRef @@ -381,12 +381,6 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) factor = (ordersConverged - oStart) / (oEnd - oStart) end if - ! Compute the constant force factor - F_fact = factor * actuatorRegions(iRegion)%force / actuatorRegions(iRegion)%volume / pRef - - ! Heat factor. This is heat added per unit volume per unit time - Q_fact = factor * actuatorRegions(iRegion)%heat / actuatorRegions(iRegion)%volume / (pRef * uRef * LRef * LRef) - ! Loop over the ranges for this block iStart = actuatorRegions(iRegion)%blkPtr(nn - 1) + 1 iEnd = actuatorRegions(iRegion)%blkPtr(nn) @@ -400,25 +394,29 @@ subroutine sourceTerms_block(nn, res, iRegion, pLocal) k = actuatorRegions(iRegion)%cellIDs(3, ii) ! This actually gets the force - FTmp = vol(i, j, k) * F_fact + Fx = factor * actuatorRegions(iRegion)%force(1, ii) / pRef + Fy = factor * actuatorRegions(iRegion)%force(2, ii) / pRef + Fz = factor * actuatorRegions(iRegion)%force(3, ii) / pRef Vx = w(i, j, k, iVx) Vy = w(i, j, k, iVy) Vz = w(i, j, k, iVz) ! this gets the heat addition rate - QTmp = vol(i, j, k) * Q_fact + Q = factor * actuatorRegions(iRegion)%heat(ii) / (pRef * uRef * LRef * LRef) if (res) then ! Momentum residuals - dw(i, j, k, imx:imz) = dw(i, j, k, imx:imz) - Ftmp + dw(i, j, k, imx) = dw(i, j, k, imx) - Fx + dw(i, j, k, imy) = dw(i, j, k, imy) - Fy + dw(i, j, k, imz) = dw(i, j, k, imz) - Fz ! energy residuals dw(i, j, k, iRhoE) = dw(i, j, k, iRhoE) - & - Ftmp(1) * Vx - Ftmp(2) * Vy - Ftmp(3) * Vz - Qtmp + Fx * Vx - Fy * Vy - Fz * Vz - Q else ! Add in the local power contribution: - pLocal = pLocal + (Vx * Ftmp(1) + Vy * FTmp(2) + Vz * Ftmp(3)) * reDim + pLocal = pLocal + (Vx * Fx + Vy * Fy + Vz * Fz) * reDim end if end do From 5d49abf1f195edb886d8efb443e6e4b6d0d7084d Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Wed, 18 Jun 2025 08:42:27 +0200 Subject: [PATCH 30/49] Check inputs to ActuatorRegion class --- adflow/actuatorRegion.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index dbd26e3de..522b15905 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -7,10 +7,15 @@ class AbstractActuatorRegion(ABC): def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray): - # todo add error checking + if centerPoint.shape != (3,): + raise ValueError('"centerPoint" must have shape "(3,)"') + if thrustVector.shape != (3,): + raise ValueError('"thrustVector" must have shape "(3,)"') + if np.linalg.norm(thrustVector) == 0: + raise ValueError('"trustVector" can not have a length of "0"') self.centerPoint = centerPoint - self.thrustVector = thrustVector + self.thrustVector = thrustVector / np.linalg.norm(thrustVector) self.iRegion = -1 self.nLocalCells = -1 From d73e35467dd2840419e0228b20e4fb36c25853f9 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Wed, 18 Jun 2025 08:56:39 +0200 Subject: [PATCH 31/49] fix bug where procs with 0 AR cells would crash --- adflow/pyADflow.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 7bb258c89..7c2dbc316 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -913,6 +913,9 @@ def _updateActuatorRegionsBC(self): totalVolume = self.comm.allreduce(numpy.sum(volume), op=MPI.SUM) + # skip this proc if no cells are active + if actuatorRegion.nLocalCells == 0: + continue # compute the BC force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, volume, totalVolume) From 1b9f33d082b5df619ae9297bcd87d131b804b62f Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Wed, 18 Jun 2025 10:03:52 +0200 Subject: [PATCH 32/49] Plug AR BCs into existing aeroProblem BC system --- adflow/actuatorRegion.py | 25 ++++++++++++++++++++----- adflow/pyADflow.py | 16 ++++++++++++---- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 522b15905..fd50b19f7 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -18,6 +18,14 @@ def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray): self.thrustVector = thrustVector / np.linalg.norm(thrustVector) self.iRegion = -1 self.nLocalCells = -1 + self.familyName = None + self._boundaryConditions = dict() + + def setBCValue(self, bcName, bcValue): + if bcName not in self._boundaryConditions.keys(): + raise ValueError(f'"{bcName}" is not a valid boundary Condition. Valid Conditions are: {list(self._boundaryConditions.keys())}') + + self._boundaryConditions[bcName] = bcValue @abstractmethod def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray) -> npt.NDArray: @@ -39,7 +47,7 @@ def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt. class UniformActuatorRegion(AbstractActuatorRegion): - def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, outerDiameter: float, regionDepth: float, thrust: float, heat: float): + def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, outerDiameter: float, regionDepth: float, thrust: float = 0., heat: float = 0.): super().__init__(centerPoint, thrustVector) if regionDepth <= 0: @@ -53,9 +61,14 @@ def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, outerDia self._outerDiameter = outerDiameter self._regionDepth = regionDepth - self._thrust = thrust - self._heat = heat + self._heatBcName = 'Heat' + self._thrustBcName = 'Thrust' + + self._boundaryConditions = { + self._thrustBcName: thrust, + self._heatBcName: heat, + } def tagActiveCells(self, distance2axis, distance2plane): flags = np.zeros_like(distance2axis) @@ -74,9 +87,10 @@ def tagActiveCells(self, distance2axis, distance2plane): def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float): force = np.zeros((len(distance2axis), 3)) + thrustBC = self._boundaryConditions[self._thrustBcName] force[:, :] = np.outer( - self._thrust * cellVolume / totalVolume, + thrustBC * cellVolume / totalVolume, self.thrustVector ) @@ -84,8 +98,9 @@ def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float): heat = np.zeros_like(distance2axis) + heatBC = self._boundaryConditions[self._heatBcName] - heat = self._heat * cellVolume / totalVolume + heat = heatBC * cellVolume / totalVolume return heat diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 7c2dbc316..25a446ea7 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -896,13 +896,21 @@ def addActuatorRegion( ) actuatorRegion.iRegion = iRegion actuatorRegion.nLocalCells = nLocalCells + actuatorRegion.familyName = familyName # book keep the new region self._actuatorRegions.append(actuatorRegion) - def _updateActuatorRegionsBC(self): + def _updateActuatorRegionsBC(self, aeroproblem): for actuatorRegion in self._actuatorRegions: + # set BC values + for (bcName, familyName), bcValue in aeroproblem.bcVarData.items(): + if familyName != actuatorRegion.familyName: + continue + actuatorRegion.setBCValue(bcName, bcValue) + + # compute local metrics distance2plane, distance2axis, volume = self.adflow.actuatorregion.computespatialmetrics( actuatorRegion.iRegion, @@ -917,11 +925,11 @@ def _updateActuatorRegionsBC(self): if actuatorRegion.nLocalCells == 0: continue - # compute the BC + # compute the source terms force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, volume, totalVolume) heat = actuatorRegion.computeCellHeatVector(distance2axis, distance2plane, volume, totalVolume) - # set the BC value in Fortran + # apply the source terms in Fortran self.adflow.actuatorregion.populatebcvalues( actuatorRegion.iRegion, actuatorRegion.nLocalCells, @@ -3650,7 +3658,7 @@ def _setAeroProblemData(self, aeroProblem, firstCall=False): if not empty: self.adflow.bcdata.setbcdata(nameArray, dataArray, groupArray, 1) - self._updateActuatorRegionsBC() + self._updateActuatorRegionsBC(AP) if not firstCall: self.adflow.initializeflow.updatebcdataalllevels() From 5f5919327f5c186eabe546f32003346fa958aa78 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Wed, 18 Jun 2025 10:31:17 +0200 Subject: [PATCH 33/49] Adjust actuator_test to new setup (non gradients tests pass!) --- tests/reg_tests/test_actuator.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/reg_tests/test_actuator.py b/tests/reg_tests/test_actuator.py index bd13bca0f..718d77493 100644 --- a/tests/reg_tests/test_actuator.py +++ b/tests/reg_tests/test_actuator.py @@ -13,6 +13,8 @@ from pygeo import DVGeometry from adflow import ADFLOW_C +from adflow.actuatorRegion import UniformActuatorRegion + # import the testing utilities import reg_test_utils as utils from reg_default_options import adflowDefOpts @@ -91,18 +93,19 @@ def setUp(self): # this is imported from reg_aeroproblems utility script self.ap = ap_actuator_pipe - actuatorFile = os.path.join(baseDir, "../../input_files/actuator_test_disk.xyz") + actuator_region = UniformActuatorRegion( + centerPoint = np.array([-0.38, 0, 0.3]), + thrustVector = np.array([1, 0, 0]), + outerDiameter = 0.354, + regionDepth = 0.12, + thrust = 0, + heat = 0, + ) + self.CFDSolver.addActuatorRegion( - actuatorFile, - "uniform", - np.array([0, 0, 0]), - np.array([1, 0, 0]), - "actuator_region", - # we will set these individually in the tests below - thrust=0.0, - torque=0.0, - heat=0.0, - ) + actuator_region, + 'actuator_region', + ) # add thrust and heat as AP DVs self.ap.setBCVar("Thrust", 0.0, "actuator_region") From 08df87413c0ffffe0edd12884600e88c7217ca96 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 20 Jun 2025 11:50:55 +0200 Subject: [PATCH 34/49] Remove actuator region code from BC routines --- src/bcdata/BCData.F90 | 70 ------------------------------------------- 1 file changed, 70 deletions(-) diff --git a/src/bcdata/BCData.F90 b/src/bcdata/BCData.F90 index a6d61ae80..6599cbdb4 100644 --- a/src/bcdata/BCData.F90 +++ b/src/bcdata/BCData.F90 @@ -1413,7 +1413,6 @@ subroutine setBCData(bcDataNamesIn, bcDataIn, famLists, sps, & use sorting, only: famInList use utils, only: setPointers, terminate, char2str use communication, only: myid - use actuatorRegionData, only: actuatorRegions, nActuatorRegions ! ! Subroutine arguments. ! @@ -1475,27 +1474,6 @@ subroutine setBCData(bcDataNamesIn, bcDataIn, famLists, sps, & end do varLoop end do domainsLoop - ! ! Loop over any actuator regions since they also could have to set BCData - ! regionLoop: do iRegion = 1, nActuatorRegions - ! varLoop2: do iVar = 1, nVar - ! nFam = famLists(iVar, 1) - ! famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then - - ! ! Extract the name - ! varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) - - ! if (trim(varName) == "Thrust") then - ! actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & - ! bcDataIn(iVar) - ! else if (trim(varName) == "Torque") then - ! actuatorRegions(iRegion)%torque = bcDataIn(iVar) - ! else if (trim(varName) == "Heat") then - ! actuatorRegions(iRegion)%heat = bcDataIn(iVar) - ! end if - ! end if famInclude2 - ! end do varLoop2 - ! end do regionLoop - end subroutine setBCData subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & @@ -1509,7 +1487,6 @@ subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & cgnsSubFace, BCType use sorting, only: famInList use utils, only: setPointers_d, terminate, char2str - use actuatorRegionData, only: actuatorRegionsd, actuatorRegions, nActuatorRegions ! ! Subroutine arguments. ! @@ -1573,31 +1550,6 @@ subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & end do varLoop end do domainsLoop - ! ! Loop over any actuator regions since they also could have to set BCData - ! regionLoop: do iRegion = 1, nActuatorRegions - ! varLoop2: do iVar = 1, nVar - ! nFam = famLists(iVar, 1) - ! famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then - - ! ! Extract the name - ! varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) - - ! if (trim(varName) == "Thrust") then - ! actuatorRegions(iRegion)%force = actuatorRegions(iRegion)%axisVec * & - ! bcDataIn(iVar) - ! actuatorRegionsd(iRegion)%force = actuatorRegions(iRegion)%axisVec * & - ! bcDataInd(iVar) - ! else if (trim(varName) == "Torque") then - ! actuatorRegions(iRegion)%torque = bcDataIn(iVar) - ! actuatorRegionsd(iRegion)%torque = bcDataInd(iVar) - ! else if (trim(varName) == "Heat") then - ! actuatorRegions(iRegion)%heat = bcDataIn(iVar) - ! actuatorRegionsd(iRegion)%heat = bcDataInd(iVar) - ! end if - ! end if famInclude2 - ! end do varLoop2 - ! end do regionLoop - end subroutine setBCData_d subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & @@ -1611,7 +1563,6 @@ subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & cgnsSubFace, BCType use sorting, only: famInList use utils, only: setPointers_b, terminate, char2str - use actuatorRegionData, only: actuatorRegionsd, actuatorRegions, nActuatorRegions ! ! Subroutine arguments. @@ -1678,27 +1629,6 @@ subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & end do varLoop end do domainsLoop - ! ! Loop over any actuator regions since they also could have to set BCData - ! regionLoop: do iRegion = 1, nActuatorRegions - ! varLoop2: do iVar = 1, nVar - ! nFam = famLists(iVar, 1) - ! famInclude2: if (famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then - - ! ! Extract the name - ! varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) - - ! if (trim(varName) == "Thrust") then - ! bcDataInd(ivar) = & - ! sum(actuatorRegions(iRegion)%axisVec * actuatorRegionsd(iRegion)%force) - ! else if (trim(varName) == "Torque") then - ! bcDataInd(ivar) = actuatorRegionsd(iRegion)%torque - ! else if (trim(varName) == "Heat") then - ! bcDataInd(ivar) = actuatorRegionsd(iRegion)%heat - ! end if - ! end if famInclude2 - ! end do varLoop2 - ! end do regionLoop - end subroutine setBCData_b subroutine extractFromDataSet(bcVarArray) From 8df783363ddb4b4966c166bc036d3d7e6d1d73d9 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 27 Jun 2025 14:09:21 +0200 Subject: [PATCH 35/49] Add BSplineActuatorRegion --- adflow/actuatorRegion.py | 142 +++++++++++++++++++++++++++------- adflow/pyADflow.py | 12 +-- src/f2py/adflow.pyf | 6 +- src/solver/actuatorRegion.F90 | 37 ++++++--- 4 files changed, 151 insertions(+), 46 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index fd50b19f7..33e71cf16 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -3,78 +3,93 @@ import numpy as np import numpy.typing as npt +import scipy.interpolate as interpolate class AbstractActuatorRegion(ABC): - def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray): + def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, thrust: float, heat: float): if centerPoint.shape != (3,): raise ValueError('"centerPoint" must have shape "(3,)"') if thrustVector.shape != (3,): raise ValueError('"thrustVector" must have shape "(3,)"') if np.linalg.norm(thrustVector) == 0: raise ValueError('"trustVector" can not have a length of "0"') + if thrust < 0: + raise ValueError('"thrust" must not be smaller than 0.') + if heat < 0: + raise ValueError('"heat" must not be smaller than 0.') + self.centerPoint = centerPoint self.thrustVector = thrustVector / np.linalg.norm(thrustVector) self.iRegion = -1 self.nLocalCells = -1 self.familyName = None - self._boundaryConditions = dict() + + + self._heatBcName = 'Heat' + self._thrustBcName = 'Thrust' + + self._boundaryConditions = { + self._thrustBcName: thrust, + self._heatBcName: heat, + } def setBCValue(self, bcName, bcValue): if bcName not in self._boundaryConditions.keys(): - raise ValueError(f'"{bcName}" is not a valid boundary Condition. Valid Conditions are: {list(self._boundaryConditions.keys())}') + raise ValueError(f'"{bcName}" is not a valid Boundary Condition. Valid Conditions are: {list(self._boundaryConditions.keys())}') self._boundaryConditions[bcName] = bcValue @abstractmethod - def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray) -> npt.NDArray: + def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray) -> npt.NDArray: flags = np.zeros_like(distance2axis) return flags @abstractmethod - def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: + def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: force = np.zeros((3, len(distance2axis))) return force @abstractmethod - def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: + def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: heat = np.zeros_like(distance2axis) return heat - - -class UniformActuatorRegion(AbstractActuatorRegion): - def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, outerDiameter: float, regionDepth: float, thrust: float = 0., heat: float = 0.): - super().__init__(centerPoint, thrustVector) +class CircularActuatorRegion(AbstractActuatorRegion): + def __init__(self, + centerPoint: npt.NDArray, + thrustVector: npt.NDArray, + innerDiameter: float, + outerDiameter: float, + regionDepth: float, + thrust: float = 0, + heat: float = 0): + super().__init__(centerPoint, thrustVector, thrust, heat) if regionDepth <= 0: raise ValueError('"depth" must be greater than 0.') + if innerDiameter < 0: + raise ValueError('"innerDiameter" must not be smaller than 0.') if outerDiameter <= 0: raise ValueError('"outerDiameter" must be greater than 0.') - if thrust < 0: - raise ValueError('"thrust" must not be smaller than 0.') - if heat < 0: - raise ValueError('"heat" must not be smaller than 0.') + if outerDiameter <= innerDiameter: + raise ValueError('"outerDiameter" must be greater than "innerDiameter".') + self._innerDiameter = innerDiameter self._outerDiameter = outerDiameter self._regionDepth = regionDepth - self._heatBcName = 'Heat' - self._thrustBcName = 'Thrust' - - self._boundaryConditions = { - self._thrustBcName: thrust, - self._heatBcName: heat, - } - - def tagActiveCells(self, distance2axis, distance2plane): + def tagActiveCells(self, distance2axis, distance2plane, tangent): flags = np.zeros_like(distance2axis) indices = np.logical_and( - distance2axis <= self._outerDiameter/2, + np.logical_and( + distance2axis >= self._innerDiameter/2, + distance2axis <= self._outerDiameter/2, + ), np.logical_and( distance2plane >= 0, distance2plane <= self._regionDepth @@ -85,7 +100,12 @@ def tagActiveCells(self, distance2axis, distance2plane): return flags - def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float): + + + + +class UniformActuatorRegion(CircularActuatorRegion): + def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): force = np.zeros((len(distance2axis), 3)) thrustBC = self._boundaryConditions[self._thrustBcName] @@ -96,7 +116,7 @@ def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt return force - def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float): + def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): heat = np.zeros_like(distance2axis) heatBC = self._boundaryConditions[self._heatBcName] @@ -104,3 +124,71 @@ def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt. return heat + + + + +class BSplineActuatorRegion(CircularActuatorRegion): + def __init__(self, + centerPoint: npt.NDArray, + thrustVector: npt.NDArray, + innerDiameter: float, + outerDiameter: float, + regionDepth: float, + thrustDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), + tangentDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), + radialDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), + heatDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), + thrust: float = 0, + heat: float = 0 + ): + super().__init__(centerPoint, thrustVector, innerDiameter, outerDiameter, regionDepth, thrust, heat) + + self._thrustSpline = interpolate.BSpline(*thrustDistribution) + self._tangentSpline = interpolate.BSpline(*tangentDistribution) + self._radialSpline = interpolate.BSpline(*radialDistribution) + self._heatSpline = interpolate.BSpline(*heatDistribution) + + def _computeNormalizedRadius(self, distance2axis): + normalizedRadius = (distance2axis - self._innerDiameter/2) / (self._outerDiameter/2 - self._innerDiameter) + return normalizedRadius + + + def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): + force = np.zeros((len(distance2axis), 3)) + thrustBC = self._boundaryConditions[self._thrustBcName] + + normalizedRadius = self._computeNormalizedRadius(distance2axis) + thrustFactor = thrustBC * cellVolume / totalVolume + + # add thrust + force[:, :] = np.outer( + self._thrustSpline(normalizedRadius) * thrustFactor, + self.thrustVector + ) + + # add swirl (tangential contribution) + force += np.multiply( + tangent.T, + np.array([self._tangentSpline(normalizedRadius) * thrustFactor]) + ).T + + # add radial contribution + radius = np.cross(tangent, self.thrustVector) + force += np.multiply( + radius.T, + np.array([self._radialSpline(normalizedRadius) * thrustFactor]) + ).T + + return force + + def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): + heat = np.zeros_like(distance2axis) + heatBC = self._boundaryConditions[self._heatBcName] + + normalizedRadius = self._computeNormalizedRadius(distance2axis) + + heat = self._heatSpline(normalizedRadius) * heatBC * cellVolume / totalVolume + + return heat + diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 25a446ea7..558e97ed5 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -879,14 +879,15 @@ def addActuatorRegion( # compute the distance of each cell to the AR plane and axis ncells = self.adflow.adjointvars.ncellslocal[0] - distance2plane, distance2axis = self.adflow.actuatorregion.computeinitialspatialmetrics( + distance2plane, distance2axis, tangent = self.adflow.actuatorregion.computeinitialspatialmetrics( actuatorRegion.centerPoint, actuatorRegion.thrustVector, ncells ) + tangent = tangent.T # tag the active cells - flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane) + flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane, tangent) iRegion, nLocalCells = self.adflow.actuatorregion.addactuatorregion( flag, familyName, @@ -912,12 +913,13 @@ def _updateActuatorRegionsBC(self, aeroproblem): # compute local metrics - distance2plane, distance2axis, volume = self.adflow.actuatorregion.computespatialmetrics( + distance2plane, distance2axis, tangent, volume = self.adflow.actuatorregion.computespatialmetrics( actuatorRegion.iRegion, actuatorRegion.nLocalCells, actuatorRegion.centerPoint, actuatorRegion.thrustVector, ) + tangent = tangent.T totalVolume = self.comm.allreduce(numpy.sum(volume), op=MPI.SUM) @@ -926,8 +928,8 @@ def _updateActuatorRegionsBC(self, aeroproblem): continue # compute the source terms - force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, volume, totalVolume) - heat = actuatorRegion.computeCellHeatVector(distance2axis, distance2plane, volume, totalVolume) + force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, tangent, volume, totalVolume) + heat = actuatorRegion.computeCellHeatVector(distance2axis, distance2plane, tangent, volume, totalVolume) # apply the source terms in Fortran self.adflow.actuatorregion.populatebcvalues( diff --git a/src/f2py/adflow.pyf b/src/f2py/adflow.pyf index 4d8352a15..3e4d147a9 100644 --- a/src/f2py/adflow.pyf +++ b/src/f2py/adflow.pyf @@ -685,12 +685,13 @@ python module libadflow end module usersurfaceintegrations module actuatorregion ! in :test:actuatorDiskRegion.F90 - subroutine computeinitialspatialmetrics(centerpoint, thrustvector, n, distance2plane, distance2axis) ! in :test:actuatorDiskRegion.F90:actuatorregion + subroutine computeinitialspatialmetrics(centerpoint, thrustvector, n, distance2plane, distance2axis, tangent) ! in :test:actuatorDiskRegion.F90:actuatorregion real(kind=realtype) dimension(3),intent(in) :: centerpoint real(kind=realtype) dimension(3),intent(in) :: thrustvector integer(kind=inttype) intent(in) :: n real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2plane real(kind=realtype) dimension(n),intent(out),depend(n) :: distance2axis + real(kind=realtype) dimension(3, n),intent(out),depend(n) :: tangent end subroutine computeinitialspatialmetrics subroutine addactuatorregion(flag,n,famname,famid,relaxstart,relaxend,iregion,nlocalcells) ! in :test:actuatorDiskRegion.F90:actuatorregion @@ -704,13 +705,14 @@ python module libadflow integer(kind=inttype), intent(out) :: nlocalcells end subroutine addactuatorregion - subroutine computespatialmetrics(iregion, nlocalcells, centerpoint, thrustvector, distance2plane, distance2axis, volume) ! in :test:actuatorDiskRegion.F90:actuatorregion + subroutine computespatialmetrics(iregion, nlocalcells, centerpoint, thrustvector, distance2plane, distance2axis, tangent, volume) ! in :test:actuatorDiskRegion.F90:actuatorregion real(kind=realtype) dimension(3),intent(in) :: centerpoint real(kind=realtype) dimension(3),intent(in) :: thrustvector integer(kind=inttype), intent(in) :: iregion integer(kind=inttype) intent(in) :: nlocalcells real(kind=realtype) dimension(nlocalcells),intent(out),depend(nlocalcells) :: distance2plane real(kind=realtype) dimension(nlocalcells),intent(out),depend(nlocalcells) :: distance2axis + real(kind=realtype) dimension(3, nlocalcells),intent(out),depend(nlocalcells) :: tangent real(kind=realtype) dimension(nlocalcells),intent(out),depend(nlocalcells) :: volume end subroutine addactuatorregion diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 72c582c8e..869382abd 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -6,7 +6,7 @@ module actuatorRegion implicit none contains - subroutine computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane, distance2axis) + subroutine computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane, distance2axis, tangent) use constants use blockPointers, only: x implicit none @@ -17,10 +17,11 @@ subroutine computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distanc ! Outputs real(kind=realType), intent(out) :: distance2axis, distance2plane + real(kind=realType), dimension(3), intent(out) :: tangent ! Working - real(kind=realType) :: thrustVectorNorm, dotProduct, norm - real(kind=realType), dimension(3) :: xCen, distance2center, crossProduct + real(kind=realType) :: thrustVectorNorm, dotProduct, tangentNorm + real(kind=realType), dimension(3) :: xCen, distance2center, rawTangent ! Compute the cell center xCen = eighth * (x(i - 1, j - 1, k - 1, :) + x(i, j - 1, k - 1, :) & @@ -36,13 +37,17 @@ subroutine computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distanc distance2plane = dotProduct / thrustVectorNorm ! compute distance to axis - crossProduct(1) = distance2center(2)*thrustVector(3) - distance2center(3)*thrustVector(2) - crossProduct(2) = distance2center(3)*thrustVector(1) - distance2center(1)*thrustVector(3) - crossProduct(3) = distance2center(1)*thrustVector(2) - distance2center(2)*thrustVector(1) + rawTangent(1) = distance2center(2)*thrustVector(3) - distance2center(3)*thrustVector(2) + rawTangent(2) = distance2center(3)*thrustVector(1) - distance2center(1)*thrustVector(3) + rawTangent(3) = distance2center(1)*thrustVector(2) - distance2center(2)*thrustVector(1) - norm = sqrt(crossProduct(1)**2 + crossProduct(2)**2 + crossProduct(3)**2) + tangentNorm = sqrt(rawTangent(1)**2 + rawTangent(2)**2 + rawTangent(3)**2) + + distance2axis = tangentNorm / thrustVectorNorm + + ! compute tangential vector + tangent = rawTangent / tangentNorm - distance2axis = norm / thrustVectorNorm end subroutine computeCellSpatialMetrics @@ -54,7 +59,7 @@ end subroutine computeCellSpatialMetrics ! ---------------------------------------------------------------------- #ifndef USE_TAPENADE - subroutine computeInitialSpatialMetrics(centerPoint, thrustVector, n, distance2plane, distance2axis) + subroutine computeInitialSpatialMetrics(centerPoint, thrustVector, n, distance2plane, distance2axis, tangent) use constants use blockPointers, only: x, il, jl, kl, nDom, iBlank @@ -65,6 +70,7 @@ subroutine computeInitialSpatialMetrics(centerPoint, thrustVector, n, distance2p real(kind=realType), dimension(3), intent(in) :: centerPoint, thrustVector integer(kind=intType), intent(in) :: n real(kind=realType), dimension(n), intent(out) :: distance2plane, distance2axis + real(kind=realType), dimension(3, n), intent(out) :: tangent ! Working variables @@ -92,7 +98,9 @@ subroutine computeInitialSpatialMetrics(centerPoint, thrustVector, n, distance2p cycle end if - call computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane(ii), distance2axis(ii)) + call computeCellSpatialMetrics(i, j, k, & + centerPoint, thrustVector, & + distance2plane(ii), distance2axis(ii), tangent(:, ii)) end do end do end do @@ -199,7 +207,8 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd, iReg end subroutine addActuatorRegion - subroutine computeSpatialMetrics(iRegion, nLocalCells, centerPoint, thrustVector, distance2plane, distance2axis, volume) + subroutine computeSpatialMetrics(iRegion, nLocalCells, centerPoint, thrustVector, & + distance2plane, distance2axis, tangent, volume) use constants use blockPointers, only: nDom, vol use utils, only: setPointers @@ -212,6 +221,7 @@ subroutine computeSpatialMetrics(iRegion, nLocalCells, centerPoint, thrustVector ! Outputs real(kind=realType), intent(out), dimension(nLocalCells) :: distance2axis, distance2plane, volume + real(kind=realType), dimension(3, nLocalCells), intent(out) :: tangent ! Working type(actuatorRegionType), pointer :: region @@ -230,7 +240,10 @@ subroutine computeSpatialMetrics(iRegion, nLocalCells, centerPoint, thrustVector k = actuatorRegions(iRegion)%cellIDs(3, iii) - call computeCellSpatialMetrics(i, j, k, centerPoint, thrustVector, distance2plane(iii), distance2axis(iii)) + call computeCellSpatialMetrics(i, j, k, & + centerPoint, thrustVector, & + distance2plane(iii), distance2axis(iii), tangent(:, iii)) + volume(iii) = vol(i, j, k) end do end do From 389516d0c3b5906a99f5f5714947b8f694ae3eb9 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 27 Jun 2025 16:32:35 +0200 Subject: [PATCH 36/49] Add ActuatoRegionHandler to move 'business logic' to its own file --- adflow/actuatorRegion.py | 109 +++++++++++++++++++++++++++++++++++---- adflow/pyADflow.py | 98 +++++------------------------------ 2 files changed, 110 insertions(+), 97 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 33e71cf16..4521cf4f6 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -1,11 +1,18 @@ from abc import ABC, abstractmethod from typing import Tuple +from types import ModuleType +import os + +from mpi4py import MPI import numpy as np import numpy.typing as npt import scipy.interpolate as interpolate +from baseclasses import AeroProblem + + class AbstractActuatorRegion(ABC): def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, thrust: float, heat: float): if centerPoint.shape != (3,): @@ -24,7 +31,7 @@ def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, thrust: self.thrustVector = thrustVector / np.linalg.norm(thrustVector) self.iRegion = -1 self.nLocalCells = -1 - self.familyName = None + self.familyName = '' self._heatBcName = 'Heat' @@ -57,6 +64,90 @@ def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt. return heat +class ActuatorRegionHandler(): + def __init__(self): + + self._actuatorRegions = list() + + def addActuatorRegion(self, actuatorRegion: AbstractActuatorRegion, adflow_fortran: ModuleType, familyName: str, familyID: int, relaxStart: float, relaxEnd: float): + # compute the distance of each cell to the AR plane and axis + ncells = adflow_fortran.adjointvars.ncellslocal[0] + + distance2plane, distance2axis, tangent = adflow_fortran.actuatorregion.computeinitialspatialmetrics( + actuatorRegion.centerPoint, + actuatorRegion.thrustVector, + ncells + ) + tangent = tangent.T + + # tag the active cells + flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane, tangent) + iRegion, nLocalCells = adflow_fortran.actuatorregion.addactuatorregion( + flag, + familyName, + familyID, + relaxStart, + relaxEnd, + ) + actuatorRegion.iRegion = iRegion + actuatorRegion.nLocalCells = nLocalCells + actuatorRegion.familyName = familyName + + # book keep the new region + self._actuatorRegions.append(actuatorRegion) + + def updateActuatorRegionsBC(self, aeroproblem: AeroProblem, adflow_fortran: ModuleType, comm: MPI.Intracomm): + for actuatorRegion in self._actuatorRegions: + + # set BC values + for (bcName, familyName), bcValue in aeroproblem.bcVarData.items(): + if familyName != actuatorRegion.familyName: + continue + actuatorRegion.setBCValue(bcName, bcValue) + + + # compute local metrics + distance2plane, distance2axis, tangent, volume = adflow_fortran.actuatorregion.computespatialmetrics( + actuatorRegion.iRegion, + actuatorRegion.nLocalCells, + actuatorRegion.centerPoint, + actuatorRegion.thrustVector, + ) + tangent = tangent.T + + totalVolume = comm.allreduce(np.sum(volume), op=MPI.SUM) + + # skip this proc if no cells are active + if actuatorRegion.nLocalCells == 0: + continue + + # compute the source terms + force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, tangent, volume, totalVolume) + heat = actuatorRegion.computeCellHeatVector(distance2axis, distance2plane, tangent, volume, totalVolume) + + # apply the source terms in Fortran + adflow_fortran.actuatorregion.populatebcvalues( + actuatorRegion.iRegion, + actuatorRegion.nLocalCells, + force.T, + heat.T, + ) + + def writeActuatorRegions(self, adflow_fortran: ModuleType, fileName: str, outputDir: str): + # Join to get the actual filename root + fileName = os.path.join(outputDir, fileName) + + # Ensure extension is .plt even if the user didn't specify + fileName, ext = os.path.splitext(fileName) + fileName += ".plt" + + # just call the underlying fortran routine + adflow_fortran.actuatorregion.writeactuatorregions(fileName) + + + + + class CircularActuatorRegion(AbstractActuatorRegion): def __init__(self, @@ -106,10 +197,9 @@ def tagActiveCells(self, distance2axis, distance2plane, tangent): class UniformActuatorRegion(CircularActuatorRegion): def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): - force = np.zeros((len(distance2axis), 3)) thrustBC = self._boundaryConditions[self._thrustBcName] - force[:, :] = np.outer( + force = np.outer( thrustBC * cellVolume / totalVolume, self.thrustVector ) @@ -117,7 +207,6 @@ def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVol return force def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): - heat = np.zeros_like(distance2axis) heatBC = self._boundaryConditions[self._heatBcName] heat = heatBC * cellVolume / totalVolume @@ -155,35 +244,33 @@ def _computeNormalizedRadius(self, distance2axis): def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): - force = np.zeros((len(distance2axis), 3)) thrustBC = self._boundaryConditions[self._thrustBcName] normalizedRadius = self._computeNormalizedRadius(distance2axis) thrustFactor = thrustBC * cellVolume / totalVolume - # add thrust - force[:, :] = np.outer( + # add axial contribution (thrust) + force = np.outer( self._thrustSpline(normalizedRadius) * thrustFactor, self.thrustVector ) - # add swirl (tangential contribution) + # add tangential contribution (swirl) force += np.multiply( tangent.T, np.array([self._tangentSpline(normalizedRadius) * thrustFactor]) ).T # add radial contribution - radius = np.cross(tangent, self.thrustVector) + radius = np.cross(self.thrustVector, tangent) force += np.multiply( radius.T, - np.array([self._radialSpline(normalizedRadius) * thrustFactor]) + np.array([self._radialSpline(normalizedRadius)*2 * thrustFactor]) ).T return force def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): - heat = np.zeros_like(distance2axis) heatBC = self._boundaryConditions[self._heatBcName] normalizedRadius = self._computeNormalizedRadius(distance2axis) diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 558e97ed5..44873f475 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -33,7 +33,7 @@ from . import MExt import hashlib from collections import OrderedDict -from .actuatorRegion import AbstractActuatorRegion +from .actuatorRegion import ActuatorRegionHandler, AbstractActuatorRegion class ADFLOWWarning(object): @@ -203,8 +203,7 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"): # had we read in a param file self.adflow.iteration.deforming_grid = True - - self._actuatorRegions = list() + self._actuatorRegionHandler = ActuatorRegionHandler() # In order to properly initialize we need to have mach number # and a few other things set. Just create a dummy aeroproblem, @@ -839,8 +838,8 @@ def addActuatorRegion( self, actuatorRegion: AbstractActuatorRegion, familyName, - relaxStart=None, - relaxEnd=None, + relaxStart=-1, + relaxEnd=-1, ): # ActuatorDiskRegions cannot be used in timeSpectralMode if self.getOption("equationMode").lower() == "time spectral": @@ -860,85 +859,19 @@ def addActuatorRegion( for fam in self.families: if len(self.families[fam]) > 0: maxInd = max(maxInd, numpy.max(self.families[fam])) - famID = maxInd + 1 - self.families[familyName.lower()] = [famID] + familyID = maxInd + 1 + self.families[familyName.lower()] = [familyID] - if relaxStart is None and relaxEnd is None: - # No relaxation at all - relaxStart = -1.0 - relaxEnd = -1.0 - - if relaxStart is None and relaxEnd is not None: - # Start at 0 orders if start is not given + if relaxStart < 0 and relaxEnd > 0: relaxStart = 0.0 - if relaxEnd is None and relaxStart is not None: - raise Error("relaxEnd must be given is relaxStart is specified") - - - # compute the distance of each cell to the AR plane and axis - ncells = self.adflow.adjointvars.ncellslocal[0] - - distance2plane, distance2axis, tangent = self.adflow.actuatorregion.computeinitialspatialmetrics( - actuatorRegion.centerPoint, - actuatorRegion.thrustVector, - ncells - ) - tangent = tangent.T - - # tag the active cells - flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane, tangent) - iRegion, nLocalCells = self.adflow.actuatorregion.addactuatorregion( - flag, - familyName, - famID, - relaxStart, - relaxEnd, - ) - actuatorRegion.iRegion = iRegion - actuatorRegion.nLocalCells = nLocalCells - actuatorRegion.familyName = familyName - - # book keep the new region - self._actuatorRegions.append(actuatorRegion) + if relaxEnd < 0 and relaxStart >= 0: + raise ValueError("relaxEnd must be given if relaxStart is specified") - def _updateActuatorRegionsBC(self, aeroproblem): - for actuatorRegion in self._actuatorRegions: - # set BC values - for (bcName, familyName), bcValue in aeroproblem.bcVarData.items(): - if familyName != actuatorRegion.familyName: - continue - actuatorRegion.setBCValue(bcName, bcValue) + self._actuatorRegionHandler.addActuatorRegion(actuatorRegion, self.adflow, familyName, familyID, relaxStart, relaxEnd) - # compute local metrics - distance2plane, distance2axis, tangent, volume = self.adflow.actuatorregion.computespatialmetrics( - actuatorRegion.iRegion, - actuatorRegion.nLocalCells, - actuatorRegion.centerPoint, - actuatorRegion.thrustVector, - ) - tangent = tangent.T - - totalVolume = self.comm.allreduce(numpy.sum(volume), op=MPI.SUM) - - # skip this proc if no cells are active - if actuatorRegion.nLocalCells == 0: - continue - - # compute the source terms - force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, tangent, volume, totalVolume) - heat = actuatorRegion.computeCellHeatVector(distance2axis, distance2plane, tangent, volume, totalVolume) - - # apply the source terms in Fortran - self.adflow.actuatorregion.populatebcvalues( - actuatorRegion.iRegion, - actuatorRegion.nLocalCells, - force.T, - heat.T, - ) - def writeActuatorRegions(self, fileName, outputDir=None): """ Debug method that writes the cells included in actuator regions @@ -959,15 +892,8 @@ def writeActuatorRegions(self, fileName, outputDir=None): if outputDir is None: outputDir = self.getOption("outputDirectory") - # Join to get the actual filename root - fileName = os.path.join(outputDir, fileName) - - # Ensure extension is .plt even if the user didn't specify - fileName, ext = os.path.splitext(fileName) - fileName += ".plt" + self._actuatorRegionHandler.writeActuatorRegions(self.adflow, fileName, outputDir) - # just call the underlying fortran routine - self.adflow.actuatorregion.writeactuatorregions(fileName) def addUserFunction(self, funcName, functions, callBack): """Add a new function to ADflow by combining existing functions in a @@ -3660,7 +3586,7 @@ def _setAeroProblemData(self, aeroProblem, firstCall=False): if not empty: self.adflow.bcdata.setbcdata(nameArray, dataArray, groupArray, 1) - self._updateActuatorRegionsBC(AP) + self._actuatorRegionHandler.updateActuatorRegionsBC(AP, self.adflow, self.comm) if not firstCall: self.adflow.initializeflow.updatebcdataalllevels() From 27ae76c4e62bee27ef1ed629242553cd1f99e078 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 27 Jun 2025 16:50:18 +0200 Subject: [PATCH 37/49] only expose user-usable ActuatorRegions. Also fix flow tests --- adflow/__init__.py | 3 +++ tests/reg_tests/test_actuator.py | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/adflow/__init__.py b/adflow/__init__.py index 172f6ad82..33baa2569 100644 --- a/adflow/__init__.py +++ b/adflow/__init__.py @@ -6,3 +6,6 @@ from .pyADflow_C import ADFLOW_C from .oversetCheck import OversetCheck from .checkZipper import checkZipper + + +from .actuatorRegion import UniformActuatorRegion, BSplineActuatorRegion diff --git a/tests/reg_tests/test_actuator.py b/tests/reg_tests/test_actuator.py index 718d77493..392f4ada5 100644 --- a/tests/reg_tests/test_actuator.py +++ b/tests/reg_tests/test_actuator.py @@ -8,13 +8,11 @@ from mpi4py import MPI # MACH classes -from adflow import ADFLOW +from adflow import ADFLOW, UniformActuatorRegion from idwarp import USMesh from pygeo import DVGeometry from adflow import ADFLOW_C -from adflow.actuatorRegion import UniformActuatorRegion - # import the testing utilities import reg_test_utils as utils from reg_default_options import adflowDefOpts @@ -96,6 +94,7 @@ def setUp(self): actuator_region = UniformActuatorRegion( centerPoint = np.array([-0.38, 0, 0.3]), thrustVector = np.array([1, 0, 0]), + innerDiameter = 0.0, outerDiameter = 0.354, regionDepth = 0.12, thrust = 0, From b63bb1e13ad28f882a99bd5acae944fa978c1174 Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Thu, 10 Jul 2025 15:17:41 +0200 Subject: [PATCH 38/49] Run tapenade --- .../outputForward/actuatorRegion_d.f90 | 27 ++++++++++--------- .../outputReverse/actuatorRegion_b.f90 | 27 ++++++++++--------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/adjoint/outputForward/actuatorRegion_d.f90 b/src/adjoint/outputForward/actuatorRegion_d.f90 index b28ff447f..608b96aba 100644 --- a/src/adjoint/outputForward/actuatorRegion_d.f90 +++ b/src/adjoint/outputForward/actuatorRegion_d.f90 @@ -9,7 +9,7 @@ module actuatorregion_d contains subroutine computecellspatialmetrics(i, j, k, centerpoint, & -& thrustvector, distance2plane, distance2axis) +& thrustvector, distance2plane, distance2axis, tangent) use constants use blockpointers, only : x implicit none @@ -19,10 +19,11 @@ subroutine computecellspatialmetrics(i, j, k, centerpoint, & integer(kind=inttype), intent(in) :: i, j, k ! outputs real(kind=realtype), intent(out) :: distance2axis, distance2plane + real(kind=realtype), dimension(3), intent(out) :: tangent ! working - real(kind=realtype) :: thrustvectornorm, dotproduct, norm + real(kind=realtype) :: thrustvectornorm, dotproduct, tangentnorm real(kind=realtype), dimension(3) :: xcen, distance2center, & -& crossproduct +& rawtangent intrinsic sqrt real(kind=realtype) :: arg1 ! compute the cell center @@ -37,15 +38,17 @@ subroutine computecellspatialmetrics(i, j, k, centerpoint, & & distance2center(2) + thrustvector(3)*distance2center(3) distance2plane = dotproduct/thrustvectornorm ! compute distance to axis - crossproduct(1) = distance2center(2)*thrustvector(3) - & -& distance2center(3)*thrustvector(2) - crossproduct(2) = distance2center(3)*thrustvector(1) - & -& distance2center(1)*thrustvector(3) - crossproduct(3) = distance2center(1)*thrustvector(2) - & -& distance2center(2)*thrustvector(1) - arg1 = crossproduct(1)**2 + crossproduct(2)**2 + crossproduct(3)**2 - norm = sqrt(arg1) - distance2axis = norm/thrustvectornorm + rawtangent(1) = distance2center(2)*thrustvector(3) - distance2center& +& (3)*thrustvector(2) + rawtangent(2) = distance2center(3)*thrustvector(1) - distance2center& +& (1)*thrustvector(3) + rawtangent(3) = distance2center(1)*thrustvector(2) - distance2center& +& (2)*thrustvector(1) + arg1 = rawtangent(1)**2 + rawtangent(2)**2 + rawtangent(3)**2 + tangentnorm = sqrt(arg1) + distance2axis = tangentnorm/thrustvectornorm +! compute tangential vector + tangent = rawtangent/tangentnorm end subroutine computecellspatialmetrics ! ---------------------------------------------------------------------- ! | diff --git a/src/adjoint/outputReverse/actuatorRegion_b.f90 b/src/adjoint/outputReverse/actuatorRegion_b.f90 index b806a34cf..c74214599 100644 --- a/src/adjoint/outputReverse/actuatorRegion_b.f90 +++ b/src/adjoint/outputReverse/actuatorRegion_b.f90 @@ -9,7 +9,7 @@ module actuatorregion_b contains subroutine computecellspatialmetrics(i, j, k, centerpoint, & -& thrustvector, distance2plane, distance2axis) +& thrustvector, distance2plane, distance2axis, tangent) use constants use blockpointers, only : x implicit none @@ -19,10 +19,11 @@ subroutine computecellspatialmetrics(i, j, k, centerpoint, & integer(kind=inttype), intent(in) :: i, j, k ! outputs real(kind=realtype), intent(out) :: distance2axis, distance2plane + real(kind=realtype), dimension(3), intent(out) :: tangent ! working - real(kind=realtype) :: thrustvectornorm, dotproduct, norm + real(kind=realtype) :: thrustvectornorm, dotproduct, tangentnorm real(kind=realtype), dimension(3) :: xcen, distance2center, & -& crossproduct +& rawtangent intrinsic sqrt ! compute the cell center xcen = eighth*(x(i-1, j-1, k-1, :)+x(i, j-1, k-1, :)+x(i-1, j, k-1, & @@ -36,15 +37,17 @@ subroutine computecellspatialmetrics(i, j, k, centerpoint, & & distance2center(2) + thrustvector(3)*distance2center(3) distance2plane = dotproduct/thrustvectornorm ! compute distance to axis - crossproduct(1) = distance2center(2)*thrustvector(3) - & -& distance2center(3)*thrustvector(2) - crossproduct(2) = distance2center(3)*thrustvector(1) - & -& distance2center(1)*thrustvector(3) - crossproduct(3) = distance2center(1)*thrustvector(2) - & -& distance2center(2)*thrustvector(1) - norm = sqrt(crossproduct(1)**2 + crossproduct(2)**2 + crossproduct(3& -& )**2) - distance2axis = norm/thrustvectornorm + rawtangent(1) = distance2center(2)*thrustvector(3) - distance2center& +& (3)*thrustvector(2) + rawtangent(2) = distance2center(3)*thrustvector(1) - distance2center& +& (1)*thrustvector(3) + rawtangent(3) = distance2center(1)*thrustvector(2) - distance2center& +& (2)*thrustvector(1) + tangentnorm = sqrt(rawtangent(1)**2 + rawtangent(2)**2 + rawtangent(& +& 3)**2) + distance2axis = tangentnorm/thrustvectornorm +! compute tangential vector + tangent = rawtangent/tangentnorm end subroutine computecellspatialmetrics ! ---------------------------------------------------------------------- ! | From 04872d127a386a033615b73639e4a606cc5bf4aa Mon Sep 17 00:00:00 2001 From: DavidAnderegg Date: Fri, 11 Jul 2025 09:12:56 +0200 Subject: [PATCH 39/49] Update tapenade makefile and run again --- src/adjoint/Makefile_tapenade | 4 +- src/adjoint/outputForward/residuals_d.f90 | 48 +++++++---------- src/adjoint/outputReverse/residuals_b.f90 | 63 ++++++++--------------- 3 files changed, 42 insertions(+), 73 deletions(-) diff --git a/src/adjoint/Makefile_tapenade b/src/adjoint/Makefile_tapenade index 740b99082..678ba2d62 100644 --- a/src/adjoint/Makefile_tapenade +++ b/src/adjoint/Makefile_tapenade @@ -180,8 +180,8 @@ sa%saViscous(w, vol, si, sj, sk, rlv, scratch) > \ sa%saResScale(scratch, dw) > \ (dw) \ \ -residuals%sourceTerms_block(w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) > \ - (w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%thrust, actuatorRegions%heat, actuatorRegions%volume) \ +residuals%sourceTerms_block(w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%heat) > \ + (w, pref, uref, plocal, dw, vol, actuatorRegions%force, actuatorRegions%heat) \ \ residuals%initres_block(dw, fw, flowDoms%w, flowDoms%vol, dscalar, dvector) > \ (dw, fw, flowDoms%w, flowDoms%vol, dscalar, dvector) \ diff --git a/src/adjoint/outputForward/residuals_d.f90 b/src/adjoint/outputForward/residuals_d.f90 index 0356bd2c4..09e7c3771 100644 --- a/src/adjoint/outputForward/residuals_d.f90 +++ b/src/adjoint/outputForward/residuals_d.f90 @@ -341,11 +341,9 @@ end subroutine residual_block ! differentiation of sourceterms_block in forward (tangent) mode (with options i4 dr8 r8): ! variations of useful results: *dw plocal ! with respect to varying inputs: uref pref *w *dw *(actuatorregions.force) -! *(actuatorregions.heat) actuatorregions.relaxstart -! actuatorregions.relaxend plocal +! *(actuatorregions.heat) plocal ! rw status of diff variables: uref:in pref:in *w:in *dw:in-out ! *(actuatorregions.force):in *(actuatorregions.heat):in -! actuatorregions.relaxstart:in actuatorregions.relaxend:in ! plocal:in-out ! plus diff mem management of: w:in dw:in actuatorregions.force:in ! actuatorregions.heat:in @@ -368,8 +366,7 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) integer(kind=inttype) :: i, j, k, ii, istart, iend real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & & ostart, oend - real(kind=realtype) :: vxd, vyd, vzd, fxd, fyd, fzd, qd, redimd, & -& factord, ostartd, oendd + real(kind=realtype) :: vxd, vyd, vzd, fxd, fyd, fzd, qd, redimd real(kind=realtype) :: temp real(kind=realtype) :: temp0 redimd = uref*prefd + pref*urefd @@ -378,20 +375,14 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) ! how far we are into the ramp: if (ordersconverged .lt. actuatorregions(iregion)%relaxstart) then factor = zero - factord = 0.0_8 else if (ordersconverged .gt. actuatorregions(iregion)%relaxend) & & then factor = one - factord = 0.0_8 else ! in between - ostartd = actuatorregionsd(iregion)%relaxstart ostart = actuatorregions(iregion)%relaxstart - oendd = actuatorregionsd(iregion)%relaxend oend = actuatorregions(iregion)%relaxend - temp = (ordersconverged-ostart)/(oend-ostart) - factord = (-ostartd-temp*(oendd-ostartd))/(oend-ostart) - factor = temp + factor = (ordersconverged-ostart)/(oend-ostart) end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 @@ -402,18 +393,18 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) j = actuatorregions(iregion)%cellids(2, ii) k = actuatorregions(iregion)%cellids(3, ii) ! this actually gets the force - temp = factor/pref - fxd = temp*actuatorregionsd(iregion)%force(1, ii) + & -& actuatorregions(iregion)%force(1, ii)*(factord-temp*prefd)/pref - fx = actuatorregions(iregion)%force(1, ii)*temp - temp = factor/pref - fyd = temp*actuatorregionsd(iregion)%force(2, ii) + & -& actuatorregions(iregion)%force(2, ii)*(factord-temp*prefd)/pref - fy = actuatorregions(iregion)%force(2, ii)*temp - temp = factor/pref - fzd = temp*actuatorregionsd(iregion)%force(3, ii) + & -& actuatorregions(iregion)%force(3, ii)*(factord-temp*prefd)/pref - fz = actuatorregions(iregion)%force(3, ii)*temp + temp = actuatorregions(iregion)%force(1, ii)/pref + fxd = factor*(actuatorregionsd(iregion)%force(1, ii)-temp*prefd)/& +& pref + fx = factor*temp + temp = actuatorregions(iregion)%force(2, ii)/pref + fyd = factor*(actuatorregionsd(iregion)%force(2, ii)-temp*prefd)/& +& pref + fy = factor*temp + temp = actuatorregions(iregion)%force(3, ii)/pref + fzd = factor*(actuatorregionsd(iregion)%force(3, ii)-temp*prefd)/& +& pref + fz = factor*temp vxd = wd(i, j, k, ivx) vx = w(i, j, k, ivx) vyd = wd(i, j, k, ivy) @@ -422,11 +413,10 @@ subroutine sourceterms_block_d(nn, res, iregion, plocal, plocald) vz = w(i, j, k, ivz) ! this gets the heat addition rate temp = lref*lref*pref*uref - temp0 = factor*actuatorregions(iregion)%heat(ii)/temp - qd = (actuatorregions(iregion)%heat(ii)*factord+factor*& -& actuatorregionsd(iregion)%heat(ii)-temp0*lref**2*(uref*prefd+& -& pref*urefd))/temp - q = temp0 + temp0 = actuatorregions(iregion)%heat(ii)/temp + qd = factor*(actuatorregionsd(iregion)%heat(ii)-temp0*lref**2*(& +& uref*prefd+pref*urefd))/temp + q = factor*temp0 if (res) then ! momentum residuals dwd(i, j, k, imx) = dwd(i, j, k, imx) - fxd diff --git a/src/adjoint/outputReverse/residuals_b.f90 b/src/adjoint/outputReverse/residuals_b.f90 index e9ed7e9bb..883ed69a7 100644 --- a/src/adjoint/outputReverse/residuals_b.f90 +++ b/src/adjoint/outputReverse/residuals_b.f90 @@ -336,14 +336,11 @@ end subroutine residual_block ! differentiation of sourceterms_block in reverse (adjoint) mode (with options noisize i4 dr8 r8): ! gradient of useful results: uref pref *w *dw *(actuatorregions.force) -! *(actuatorregions.heat) actuatorregions.relaxstart -! actuatorregions.relaxend plocal +! *(actuatorregions.heat) plocal ! with respect to varying inputs: uref pref *w *dw *(actuatorregions.force) -! *(actuatorregions.heat) actuatorregions.relaxstart -! actuatorregions.relaxend plocal +! *(actuatorregions.heat) plocal ! rw status of diff variables: uref:incr pref:incr *w:incr *dw:in-out ! *(actuatorregions.force):incr *(actuatorregions.heat):incr -! actuatorregions.relaxstart:incr actuatorregions.relaxend:incr ! plocal:in-out ! plus diff mem management of: w:in dw:in actuatorregions.force:in ! actuatorregions.heat:in @@ -366,10 +363,9 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) integer(kind=inttype) :: i, j, k, ii, istart, iend real(kind=realtype) :: vx, vy, vz, fx, fy, fz, q, redim, factor, & & ostart, oend - real(kind=realtype) :: vxd, vyd, vzd, fxd, fyd, fzd, qd, redimd, & -& factord, ostartd, oendd - real(kind=realtype) :: tempd + real(kind=realtype) :: vxd, vyd, vzd, fxd, fyd, fzd, qd, redimd real(kind=realtype) :: temp + real(kind=realtype) :: tempd real(kind=realtype) :: tempd0 real(kind=realtype) :: tempd1 integer :: branch @@ -377,24 +373,23 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) ! compute the relaxation factor based on the ordersconverged ! how far we are into the ramp: if (ordersconverged .lt. actuatorregions(iregion)%relaxstart) then - call pushcontrol2b(0) + call pushcontrol1b(0) factor = zero else if (ordersconverged .gt. actuatorregions(iregion)%relaxend) & & then - call pushcontrol2b(1) + call pushcontrol1b(1) factor = one else + call pushcontrol1b(1) ! in between ostart = actuatorregions(iregion)%relaxstart oend = actuatorregions(iregion)%relaxend factor = (ordersconverged-ostart)/(oend-ostart) - call pushcontrol2b(2) end if ! loop over the ranges for this block istart = actuatorregions(iregion)%blkptr(nn-1) + 1 iend = actuatorregions(iregion)%blkptr(nn) redimd = 0.0_8 - factord = 0.0_8 !$bwd-of ii-loop do ii=istart,iend ! extract the cell id. @@ -428,46 +423,30 @@ subroutine sourceterms_block_b(nn, res, iregion, plocal, plocald) fzd = vz*tempd1 qd = 0.0_8 end if - tempd0 = actuatorregions(iregion)%force(3, ii)*fzd/pref + tempd = factor*fzd/pref temp = lref*lref*pref*uref - tempd = qd/temp - factord = factord + actuatorregions(iregion)%heat(ii)*tempd + & -& tempd0 + tempd0 = factor*qd/temp actuatorregionsd(iregion)%heat(ii) = actuatorregionsd(iregion)%& -& heat(ii) + factor*tempd - tempd1 = -(lref**2*factor*actuatorregions(iregion)%heat(ii)*tempd/& -& temp) - prefd = prefd + uref*tempd1 - factor*tempd0/pref +& heat(ii) + tempd0 + tempd1 = -(lref**2*actuatorregions(iregion)%heat(ii)*tempd0/temp) + prefd = prefd + uref*tempd1 - actuatorregions(iregion)%force(3, ii& +& )*tempd/pref urefd = urefd + pref*tempd1 wd(i, j, k, ivz) = wd(i, j, k, ivz) + vzd wd(i, j, k, ivy) = wd(i, j, k, ivy) + vyd wd(i, j, k, ivx) = wd(i, j, k, ivx) + vxd actuatorregionsd(iregion)%force(3, ii) = actuatorregionsd(iregion)& -& %force(3, ii) + factor*fzd/pref +& %force(3, ii) + tempd + tempd = factor*fyd/pref actuatorregionsd(iregion)%force(2, ii) = actuatorregionsd(iregion)& -& %force(2, ii) + factor*fyd/pref - tempd0 = actuatorregions(iregion)%force(2, ii)*fyd/pref - factord = factord + tempd0 - prefd = prefd - factor*tempd0/pref +& %force(2, ii) + tempd + prefd = prefd - actuatorregions(iregion)%force(2, ii)*tempd/pref + tempd = factor*fxd/pref actuatorregionsd(iregion)%force(1, ii) = actuatorregionsd(iregion)& -& %force(1, ii) + factor*fxd/pref - tempd0 = actuatorregions(iregion)%force(1, ii)*fxd/pref - factord = factord + tempd0 - prefd = prefd - factor*tempd0/pref +& %force(1, ii) + tempd + prefd = prefd - actuatorregions(iregion)%force(1, ii)*tempd/pref end do - call popcontrol2b(branch) - if (branch .ne. 0) then - if (branch .ne. 1) then - tempd = factord/(oend-ostart) - tempd0 = -((ordersconverged-ostart)*tempd/(oend-ostart)) - ostartd = -tempd - tempd0 - oendd = tempd0 - actuatorregionsd(iregion)%relaxend = actuatorregionsd(iregion)%& -& relaxend + oendd - actuatorregionsd(iregion)%relaxstart = actuatorregionsd(iregion)& -& %relaxstart + ostartd - end if - end if + call popcontrol1b(branch) prefd = prefd + uref*redimd urefd = urefd + pref*redimd end subroutine sourceterms_block_b From f01b6255821f7ecdf31cd72858ba83bb9192d719 Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Tue, 23 Sep 2025 11:47:54 +0200 Subject: [PATCH 40/49] zero seeds for Actuator Region --- src/bcdata/BCData.F90 | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/bcdata/BCData.F90 b/src/bcdata/BCData.F90 index 6599cbdb4..14837f94e 100644 --- a/src/bcdata/BCData.F90 +++ b/src/bcdata/BCData.F90 @@ -1487,6 +1487,7 @@ subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & cgnsSubFace, BCType use sorting, only: famInList use utils, only: setPointers_d, terminate, char2str + use actuatorRegionData, only: actuatorRegionsd, actuatorRegions, nActuatorRegions ! ! Subroutine arguments. ! @@ -1550,6 +1551,19 @@ subroutine setBCData_d(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & end do varLoop end do domainsLoop + ! Loop over any actuator regions and set the seeds to 0 (this is a temporary fix until the BC seeds can be set in python) + regionLoop: do iRegion = 1, nActuatorRegions + varLoop2: do iVar = 1, nVar + nFam = famLists(iVar, 1) + if (.not. famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then + cycle + end if + + actuatorRegionsd(iRegion)%force = zero + actuatorRegionsd(iRegion)%heat = zero + end do varLoop2 + end do regionLoop + end subroutine setBCData_d subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & @@ -1563,6 +1577,7 @@ subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & cgnsSubFace, BCType use sorting, only: famInList use utils, only: setPointers_b, terminate, char2str + use actuatorRegionData, only: actuatorRegionsd, actuatorRegions, nActuatorRegions ! ! Subroutine arguments. @@ -1629,6 +1644,23 @@ subroutine setBCData_b(bcDataNamesIn, bcDataIn, bcDataInd, famLists, sps, & end do varLoop end do domainsLoop + + ! Loop over any actuator regions and set the seeds to 0 (this is a temporary fix until the BC seeds can be set in python) + regionLoop: do iRegion = 1, nActuatorRegions + varLoop2: do iVar = 1, nVar + nFam = famLists(iVar, 1) + if (.not. famInList(actuatorRegions(iRegion)%famID, famLists(iVar, 2:2 + nFam - 1))) then + cycle + end if + + ! Extract the name + varName = char2str(bcDataNamesIn(iVar, :), maxCGNSNameLen) + + bcDataInd(ivar) = zero + + end do varLoop2 + end do regionLoop + end subroutine setBCData_b subroutine extractFromDataSet(bcVarArray) From a2533ee240c0c74a45ed9828ad77286748ed811d Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Wed, 24 Sep 2025 11:15:10 +0200 Subject: [PATCH 41/49] Fix radius normalization and run black --- adflow/actuatorRegion.py | 216 ++++++++++++++++--------------- adflow/pyADflow.py | 8 +- adflow/pyPerformanceClass.py | 1 - adflow/pyWeightAndBalance.py | 8 +- adflow/pyWingCG.py | 4 +- tests/reg_tests/test_actuator.py | 20 +-- 6 files changed, 130 insertions(+), 127 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 4521cf4f6..4f2a6f066 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -16,9 +16,9 @@ class AbstractActuatorRegion(ABC): def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, thrust: float, heat: float): if centerPoint.shape != (3,): - raise ValueError('"centerPoint" must have shape "(3,)"') + raise ValueError('"centerPoint" must have shape "(3,)"') if thrustVector.shape != (3,): - raise ValueError('"thrustVector" must have shape "(3,)"') + raise ValueError('"thrustVector" must have shape "(3,)"') if np.linalg.norm(thrustVector) == 0: raise ValueError('"trustVector" can not have a length of "0"') if thrust < 0: @@ -26,69 +26,91 @@ def __init__(self, centerPoint: npt.NDArray, thrustVector: npt.NDArray, thrust: if heat < 0: raise ValueError('"heat" must not be smaller than 0.') - self.centerPoint = centerPoint self.thrustVector = thrustVector / np.linalg.norm(thrustVector) self.iRegion = -1 self.nLocalCells = -1 - self.familyName = '' - + self.familyName = "" - self._heatBcName = 'Heat' - self._thrustBcName = 'Thrust' + self._heatBcName = "Heat" + self._thrustBcName = "Thrust" self._boundaryConditions = { - self._thrustBcName: thrust, - self._heatBcName: heat, - } + self._thrustBcName: thrust, + self._heatBcName: heat, + } def setBCValue(self, bcName, bcValue): if bcName not in self._boundaryConditions.keys(): - raise ValueError(f'"{bcName}" is not a valid Boundary Condition. Valid Conditions are: {list(self._boundaryConditions.keys())}') - + raise ValueError( + f'"{bcName}" is not a valid Boundary Condition. Valid Conditions are: {list(self._boundaryConditions.keys())}' + ) + self._boundaryConditions[bcName] = bcValue @abstractmethod - def tagActiveCells(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray) -> npt.NDArray: + def tagActiveCells( + self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray + ) -> npt.NDArray: flags = np.zeros_like(distance2axis) return flags @abstractmethod - def computeCellForceVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: + def computeCellForceVector( + self, + distance2axis: npt.NDArray, + distance2plane: npt.NDArray, + tangent: npt.NDArray, + cellVolume: npt.NDArray, + totalVolume: float, + ) -> npt.NDArray: force = np.zeros((3, len(distance2axis))) return force @abstractmethod - def computeCellHeatVector(self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float) -> npt.NDArray: + def computeCellHeatVector( + self, + distance2axis: npt.NDArray, + distance2plane: npt.NDArray, + tangent: npt.NDArray, + cellVolume: npt.NDArray, + totalVolume: float, + ) -> npt.NDArray: heat = np.zeros_like(distance2axis) return heat -class ActuatorRegionHandler(): +class ActuatorRegionHandler: def __init__(self): self._actuatorRegions = list() - def addActuatorRegion(self, actuatorRegion: AbstractActuatorRegion, adflow_fortran: ModuleType, familyName: str, familyID: int, relaxStart: float, relaxEnd: float): + def addActuatorRegion( + self, + actuatorRegion: AbstractActuatorRegion, + adflow_fortran: ModuleType, + familyName: str, + familyID: int, + relaxStart: float, + relaxEnd: float, + ): # compute the distance of each cell to the AR plane and axis ncells = adflow_fortran.adjointvars.ncellslocal[0] distance2plane, distance2axis, tangent = adflow_fortran.actuatorregion.computeinitialspatialmetrics( - actuatorRegion.centerPoint, - actuatorRegion.thrustVector, - ncells + actuatorRegion.centerPoint, actuatorRegion.thrustVector, ncells ) tangent = tangent.T # tag the active cells flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane, tangent) iRegion, nLocalCells = adflow_fortran.actuatorregion.addactuatorregion( - flag, - familyName, - familyID, - relaxStart, - relaxEnd, - ) + flag, + familyName, + familyID, + relaxStart, + relaxEnd, + ) actuatorRegion.iRegion = iRegion actuatorRegion.nLocalCells = nLocalCells actuatorRegion.familyName = familyName @@ -105,14 +127,13 @@ def updateActuatorRegionsBC(self, aeroproblem: AeroProblem, adflow_fortran: Modu continue actuatorRegion.setBCValue(bcName, bcValue) - # compute local metrics distance2plane, distance2axis, tangent, volume = adflow_fortran.actuatorregion.computespatialmetrics( - actuatorRegion.iRegion, - actuatorRegion.nLocalCells, - actuatorRegion.centerPoint, - actuatorRegion.thrustVector, - ) + actuatorRegion.iRegion, + actuatorRegion.nLocalCells, + actuatorRegion.centerPoint, + actuatorRegion.thrustVector, + ) tangent = tangent.T totalVolume = comm.allreduce(np.sum(volume), op=MPI.SUM) @@ -127,11 +148,11 @@ def updateActuatorRegionsBC(self, aeroproblem: AeroProblem, adflow_fortran: Modu # apply the source terms in Fortran adflow_fortran.actuatorregion.populatebcvalues( - actuatorRegion.iRegion, - actuatorRegion.nLocalCells, + actuatorRegion.iRegion, + actuatorRegion.nLocalCells, force.T, heat.T, - ) + ) def writeActuatorRegions(self, adflow_fortran: ModuleType, fileName: str, outputDir: str): # Join to get the actual filename root @@ -145,19 +166,17 @@ def writeActuatorRegions(self, adflow_fortran: ModuleType, fileName: str, output adflow_fortran.actuatorregion.writeactuatorregions(fileName) - - - - class CircularActuatorRegion(AbstractActuatorRegion): - def __init__(self, - centerPoint: npt.NDArray, - thrustVector: npt.NDArray, - innerDiameter: float, - outerDiameter: float, - regionDepth: float, - thrust: float = 0, - heat: float = 0): + def __init__( + self, + centerPoint: npt.NDArray, + thrustVector: npt.NDArray, + innerDiameter: float, + outerDiameter: float, + regionDepth: float, + thrust: float = 0, + heat: float = 0, + ): super().__init__(centerPoint, thrustVector, thrust, heat) if regionDepth <= 0: @@ -176,33 +195,24 @@ def __init__(self, def tagActiveCells(self, distance2axis, distance2plane, tangent): flags = np.zeros_like(distance2axis) - indices = np.logical_and( - np.logical_and( - distance2axis >= self._innerDiameter/2, - distance2axis <= self._outerDiameter/2, - ), - np.logical_and( - distance2plane >= 0, - distance2plane <= self._regionDepth - ) - ) + indices = np.logical_and( + np.logical_and( + distance2axis >= self._innerDiameter / 2, + distance2axis <= self._outerDiameter / 2, + ), + np.logical_and(distance2plane >= 0, distance2plane <= self._regionDepth), + ) flags[indices] = 1 return flags - - - class UniformActuatorRegion(CircularActuatorRegion): def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): thrustBC = self._boundaryConditions[self._thrustBcName] - force = np.outer( - thrustBC * cellVolume / totalVolume, - self.thrustVector - ) + force = np.outer(thrustBC * cellVolume / totalVolume, self.thrustVector) return force @@ -214,68 +224,72 @@ def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolu return heat - - - class BSplineActuatorRegion(CircularActuatorRegion): - def __init__(self, - centerPoint: npt.NDArray, - thrustVector: npt.NDArray, - innerDiameter: float, - outerDiameter: float, - regionDepth: float, - thrustDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), - tangentDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), - radialDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), - heatDistribution: Tuple[npt.NDArray, npt.NDArray, float] = (np.array([0., 0., 1., 1.]), np.array([0., 0., 0., 0.]), 1), - thrust: float = 0, - heat: float = 0 - ): + def __init__( + self, + centerPoint: npt.NDArray, + thrustVector: npt.NDArray, + innerDiameter: float, + outerDiameter: float, + regionDepth: float, + thrustDistribution: Tuple[npt.NDArray, npt.NDArray, float] = ( + np.array([0.0, 0.0, 1.0, 1.0]), + np.array([0.0, 0.0, 0.0, 0.0]), + 1, + ), + tangentDistribution: Tuple[npt.NDArray, npt.NDArray, float] = ( + np.array([0.0, 0.0, 1.0, 1.0]), + np.array([0.0, 0.0, 0.0, 0.0]), + 1, + ), + radialDistribution: Tuple[npt.NDArray, npt.NDArray, float] = ( + np.array([0.0, 0.0, 1.0, 1.0]), + np.array([0.0, 0.0, 0.0, 0.0]), + 1, + ), + heatDistribution: Tuple[npt.NDArray, npt.NDArray, float] = ( + np.array([0.0, 0.0, 1.0, 1.0]), + np.array([0.0, 0.0, 0.0, 0.0]), + 1, + ), + thrust: float = 0, + heat: float = 0, + ): super().__init__(centerPoint, thrustVector, innerDiameter, outerDiameter, regionDepth, thrust, heat) - self._thrustSpline = interpolate.BSpline(*thrustDistribution) - self._tangentSpline = interpolate.BSpline(*tangentDistribution) - self._radialSpline = interpolate.BSpline(*radialDistribution) - self._heatSpline = interpolate.BSpline(*heatDistribution) + self._thrustSpline = interpolate.BSpline(*thrustDistribution) + self._tangentSpline = interpolate.BSpline(*tangentDistribution) + self._radialSpline = interpolate.BSpline(*radialDistribution) + self._heatSpline = interpolate.BSpline(*heatDistribution) def _computeNormalizedRadius(self, distance2axis): - normalizedRadius = (distance2axis - self._innerDiameter/2) / (self._outerDiameter/2 - self._innerDiameter) + normalizedRadius = distance2axis - self._innerDiameter / 2 + normalizedRadius /= self._outerDiameter / 2 - self._innerDiameter / 2 return normalizedRadius - def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): thrustBC = self._boundaryConditions[self._thrustBcName] - normalizedRadius = self._computeNormalizedRadius(distance2axis) + normalizedRadius = self._computeNormalizedRadius(distance2axis) thrustFactor = thrustBC * cellVolume / totalVolume # add axial contribution (thrust) - force = np.outer( - self._thrustSpline(normalizedRadius) * thrustFactor, - self.thrustVector - ) + force = np.outer(self._thrustSpline(normalizedRadius) * thrustFactor, self.thrustVector) # add tangential contribution (swirl) - force += np.multiply( - tangent.T, - np.array([self._tangentSpline(normalizedRadius) * thrustFactor]) - ).T + force += np.multiply(tangent.T, np.array([self._tangentSpline(normalizedRadius) * thrustFactor])).T # add radial contribution radius = np.cross(self.thrustVector, tangent) - force += np.multiply( - radius.T, - np.array([self._radialSpline(normalizedRadius)*2 * thrustFactor]) - ).T + force += np.multiply(radius.T, np.array([self._radialSpline(normalizedRadius) * 2 * thrustFactor])).T return force def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): heatBC = self._boundaryConditions[self._heatBcName] - normalizedRadius = self._computeNormalizedRadius(distance2axis) + normalizedRadius = self._computeNormalizedRadius(distance2axis) heat = self._heatSpline(normalizedRadius) * heatBC * cellVolume / totalVolume return heat - diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index 44873f475..efbcecd7c 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -363,7 +363,6 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"): print("| %-30s: %10.3f sec" % ("Total Init Time", finalInitTime - startInitTime)) print("+--------------------------------------------------+") - def __del__(self): """ Clean up allocated memory if necessary @@ -868,9 +867,9 @@ def addActuatorRegion( if relaxEnd < 0 and relaxStart >= 0: raise ValueError("relaxEnd must be given if relaxStart is specified") - - self._actuatorRegionHandler.addActuatorRegion(actuatorRegion, self.adflow, familyName, familyID, relaxStart, relaxEnd) - + self._actuatorRegionHandler.addActuatorRegion( + actuatorRegion, self.adflow, familyName, familyID, relaxStart, relaxEnd + ) def writeActuatorRegions(self, fileName, outputDir=None): """ @@ -894,7 +893,6 @@ def writeActuatorRegions(self, fileName, outputDir=None): self._actuatorRegionHandler.writeActuatorRegions(self.adflow, fileName, outputDir) - def addUserFunction(self, funcName, functions, callBack): """Add a new function to ADflow by combining existing functions in a user-supplied way. The allows the user to define a function diff --git a/adflow/pyPerformanceClass.py b/adflow/pyPerformanceClass.py index 5bdeb8bf1..e0f365bbb 100644 --- a/adflow/pyPerformanceClass.py +++ b/adflow/pyPerformanceClass.py @@ -29,7 +29,6 @@ class PERFORMANCE(object): - """ Basic Performance class to handle dynamic handling qualities constraints """ diff --git a/adflow/pyWeightAndBalance.py b/adflow/pyWeightAndBalance.py index 600df7135..4e81cb567 100644 --- a/adflow/pyWeightAndBalance.py +++ b/adflow/pyWeightAndBalance.py @@ -48,7 +48,6 @@ class WEIGHTANDBALANCE(Base): - """ Implementation of basic preliminary level CG and inertia estimation methods. @@ -405,12 +404,7 @@ def calculateWingInertias(self, acg, xcg): # print 'centroids',Xs,Ys,Zs3 Ix = ( - Ix - + I1x - - W * (Ys_dot**2) - - W * (Zs3**2) - + W * (Ys_dot + Ysoff) ** 2 - + W * (Zs3 + Zs1) ** 2 + Ix + I1x - W * (Ys_dot**2) - W * (Zs3**2) + W * (Ys_dot + Ysoff) ** 2 + W * (Zs3 + Zs1) ** 2 ) # print 'w',W,(Ys_dot),W*(Ys_dot**2) # Ix = Ix-W*(Ys_dot**2)#-W*(Zs3**2)+W*(Ys_dot+Ysoff)**2 + W*(Zs3+Zs1)**2 diff --git a/adflow/pyWingCG.py b/adflow/pyWingCG.py index 9f8f0b751..feaf39232 100644 --- a/adflow/pyWingCG.py +++ b/adflow/pyWingCG.py @@ -367,9 +367,7 @@ def calculateWingInertias(acg): # print 'zs3',Zs3 Zs4 = acg[i][j].z_Centroid - Ix = ( - Ix + I1x - W * (Ys_dot**2) - W * (Zs3**2) + W * (Ys_dot + Ysoff) ** 2 + W * (Zs3 + Zs1) ** 2 - ) + Ix = Ix + I1x - W * (Ys_dot**2) - W * (Zs3**2) + W * (Ys_dot + Ysoff) ** 2 + W * (Zs3 + Zs1) ** 2 Iy = Iy + I1y - W * (Xs**2) - W * (Zs3**2) + W * (Xs + Xs4) ** 2 + W * (Zs3 + Zs1) ** 2 Iz = Iz + I1z - W * (Xs**2 + Ys_dot**2) + W * (Xs + Xs4) ** 2 + W * (Ys_dot + Ysoff) ** 2 # Ixz = ... diff --git a/tests/reg_tests/test_actuator.py b/tests/reg_tests/test_actuator.py index 392f4ada5..375f13f7b 100644 --- a/tests/reg_tests/test_actuator.py +++ b/tests/reg_tests/test_actuator.py @@ -92,19 +92,19 @@ def setUp(self): self.ap = ap_actuator_pipe actuator_region = UniformActuatorRegion( - centerPoint = np.array([-0.38, 0, 0.3]), - thrustVector = np.array([1, 0, 0]), - innerDiameter = 0.0, - outerDiameter = 0.354, - regionDepth = 0.12, - thrust = 0, - heat = 0, - ) + centerPoint=np.array([-0.38, 0, 0.3]), + thrustVector=np.array([1, 0, 0]), + innerDiameter=0.0, + outerDiameter=0.354, + regionDepth=0.12, + thrust=0, + heat=0, + ) self.CFDSolver.addActuatorRegion( actuator_region, - 'actuator_region', - ) + "actuator_region", + ) # add thrust and heat as AP DVs self.ap.setBCVar("Thrust", 0.0, "actuator_region") From 533be389720787aed4edb5a846a05210947b55da Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Wed, 24 Sep 2025 14:09:04 +0200 Subject: [PATCH 42/49] reverse thrust vector direction to be consistent with nomenclature --- adflow/actuatorRegion.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 4f2a6f066..2ed6a36ed 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -212,7 +212,7 @@ class UniformActuatorRegion(CircularActuatorRegion): def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): thrustBC = self._boundaryConditions[self._thrustBcName] - force = np.outer(thrustBC * cellVolume / totalVolume, self.thrustVector) + force = np.outer(thrustBC * cellVolume / totalVolume, -self.thrustVector) return force @@ -274,7 +274,7 @@ def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVol thrustFactor = thrustBC * cellVolume / totalVolume # add axial contribution (thrust) - force = np.outer(self._thrustSpline(normalizedRadius) * thrustFactor, self.thrustVector) + force = np.outer(self._thrustSpline(normalizedRadius) * thrustFactor, -self.thrustVector) # add tangential contribution (swirl) force += np.multiply(tangent.T, np.array([self._tangentSpline(normalizedRadius) * thrustFactor])).T From a220b00aa7617fb8c39b591a1bff46d74c56a67f Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Tue, 30 Sep 2025 15:58:43 +0200 Subject: [PATCH 43/49] allocate memory for _d version aswell --- src/solver/actuatorRegion.F90 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/solver/actuatorRegion.F90 b/src/solver/actuatorRegion.F90 index 869382abd..b8d394332 100644 --- a/src/solver/actuatorRegion.F90 +++ b/src/solver/actuatorRegion.F90 @@ -205,6 +205,11 @@ subroutine addActuatorRegion(flag, n, famName, famID, relaxStart, relaxEnd, iReg allocate (region%force(3, region%nCellIDs)) allocate (region%heat(region%nCellIDs)) + + ! same for derivative seeds + allocate (actuatorRegionsd(nActuatorRegions)%force(3, region%nCellIDs)) + allocate (actuatorRegionsd(nActuatorRegions)%heat(region%nCellIDs)) + end subroutine addActuatorRegion subroutine computeSpatialMetrics(iRegion, nLocalCells, centerPoint, thrustVector, & From 0dbf1ea7361ac396c90e9e6ab695a537dd657ef6 Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Mon, 6 Oct 2025 11:16:33 +0200 Subject: [PATCH 44/49] scale thrust distribution analytically --- adflow/actuatorRegion.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 2ed6a36ed..a20ccf0d0 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -257,10 +257,37 @@ def __init__( ): super().__init__(centerPoint, thrustVector, innerDiameter, outerDiameter, regionDepth, thrust, heat) - self._thrustSpline = interpolate.BSpline(*thrustDistribution) - self._tangentSpline = interpolate.BSpline(*tangentDistribution) - self._radialSpline = interpolate.BSpline(*radialDistribution) - self._heatSpline = interpolate.BSpline(*heatDistribution) + # compute a scaling constant such that the integrated thrust equals the total prescribed thrust + scalingConstant = self._computeDistributionScalingConstant(thrustDistribution) + + self._thrustSpline = self._formSpline(thrustDistribution, scalingConstant) + self._tangentSpline = self._formSpline(tangentDistribution, scalingConstant) + self._radialSpline = self._formSpline(radialDistribution, scalingConstant) + self._heatSpline = self._formSpline(heatDistribution, scalingConstant) + + def _computeDistributionScalingConstant(self, distribution: Tuple[npt.NDArray, npt.NDArray, float]): + n_r = 1000 + r_inner = self._innerDiameter / 2 + r_outer = self._outerDiameter / 2 + d = interpolate.BSpline(*distribution) + + s = np.linspace(0, 1, n_r) + + r = r_inner + s * (r_outer - r_inner) + dr_ds = r_outer - r_inner + w = 2 * r * dr_ds / (r_outer**2 - r_inner**2) + + integral = np.trapz(d(s) * w, s) + constant = 1 / integral + + return constant + + def _formSpline(self, distribution: Tuple[npt.NDArray, npt.NDArray, float], scalingConstant: float): + t = distribution[0] + c = distribution[1] + k = distribution[2] + + return interpolate.BSpline(t, c * scalingConstant, k) def _computeNormalizedRadius(self, distance2axis): normalizedRadius = distance2axis - self._innerDiameter / 2 From 116b2412cd284418e9bb6bf1bb55c058aa49e9ad Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Mon, 6 Oct 2025 11:44:04 +0200 Subject: [PATCH 45/49] scale thrust distribution numerically --- adflow/actuatorRegion.py | 85 ++++++++++++++++++++++++++-------------- adflow/pyADflow.py | 10 ++--- 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index a20ccf0d0..aa38ab5e9 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -48,6 +48,13 @@ def setBCValue(self, bcName, bcValue): self._boundaryConditions[bcName] = bcValue + def _computeScalingConstant(self, cellValues, totalValue, comm): + if totalValue == 0: + return 1 + + computedTotalvalue = comm.allreduce(np.sum(cellValues), op=MPI.SUM) + return totalValue / computedTotalvalue + @abstractmethod def tagActiveCells( self, distance2axis: npt.NDArray, distance2plane: npt.NDArray, tangent: npt.NDArray @@ -63,6 +70,7 @@ def computeCellForceVector( tangent: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float, + comm: MPI.Intracomm, ) -> npt.NDArray: force = np.zeros((3, len(distance2axis))) return force @@ -75,36 +83,38 @@ def computeCellHeatVector( tangent: npt.NDArray, cellVolume: npt.NDArray, totalVolume: float, + comm: MPI.Intracomm, ) -> npt.NDArray: heat = np.zeros_like(distance2axis) return heat class ActuatorRegionHandler: - def __init__(self): + def __init__(self, adflow_fortran: ModuleType, comm): + self._comm = comm + self._adflow_fortran = adflow_fortran self._actuatorRegions = list() def addActuatorRegion( self, actuatorRegion: AbstractActuatorRegion, - adflow_fortran: ModuleType, familyName: str, familyID: int, relaxStart: float, relaxEnd: float, ): # compute the distance of each cell to the AR plane and axis - ncells = adflow_fortran.adjointvars.ncellslocal[0] + ncells = self._adflow_fortran.adjointvars.ncellslocal[0] - distance2plane, distance2axis, tangent = adflow_fortran.actuatorregion.computeinitialspatialmetrics( + distance2plane, distance2axis, tangent = self._adflow_fortran.actuatorregion.computeinitialspatialmetrics( actuatorRegion.centerPoint, actuatorRegion.thrustVector, ncells ) tangent = tangent.T # tag the active cells flag = actuatorRegion.tagActiveCells(distance2axis, distance2plane, tangent) - iRegion, nLocalCells = adflow_fortran.actuatorregion.addactuatorregion( + iRegion, nLocalCells = self._adflow_fortran.actuatorregion.addactuatorregion( flag, familyName, familyID, @@ -118,7 +128,7 @@ def addActuatorRegion( # book keep the new region self._actuatorRegions.append(actuatorRegion) - def updateActuatorRegionsBC(self, aeroproblem: AeroProblem, adflow_fortran: ModuleType, comm: MPI.Intracomm): + def updateActuatorRegionsBC(self, aeroproblem: AeroProblem): for actuatorRegion in self._actuatorRegions: # set BC values @@ -128,7 +138,7 @@ def updateActuatorRegionsBC(self, aeroproblem: AeroProblem, adflow_fortran: Modu actuatorRegion.setBCValue(bcName, bcValue) # compute local metrics - distance2plane, distance2axis, tangent, volume = adflow_fortran.actuatorregion.computespatialmetrics( + distance2plane, distance2axis, tangent, volume = self._adflow_fortran.actuatorregion.computespatialmetrics( actuatorRegion.iRegion, actuatorRegion.nLocalCells, actuatorRegion.centerPoint, @@ -136,18 +146,22 @@ def updateActuatorRegionsBC(self, aeroproblem: AeroProblem, adflow_fortran: Modu ) tangent = tangent.T - totalVolume = comm.allreduce(np.sum(volume), op=MPI.SUM) + totalVolume = self._comm.allreduce(np.sum(volume), op=MPI.SUM) # skip this proc if no cells are active if actuatorRegion.nLocalCells == 0: continue # compute the source terms - force = actuatorRegion.computeCellForceVector(distance2axis, distance2plane, tangent, volume, totalVolume) - heat = actuatorRegion.computeCellHeatVector(distance2axis, distance2plane, tangent, volume, totalVolume) + force = actuatorRegion.computeCellForceVector( + distance2axis, distance2plane, tangent, volume, totalVolume, self._comm + ) + heat = actuatorRegion.computeCellHeatVector( + distance2axis, distance2plane, tangent, volume, totalVolume, self._comm + ) # apply the source terms in Fortran - adflow_fortran.actuatorregion.populatebcvalues( + self._adflow_fortran.actuatorregion.populatebcvalues( actuatorRegion.iRegion, actuatorRegion.nLocalCells, force.T, @@ -209,19 +223,22 @@ def tagActiveCells(self, distance2axis, distance2plane, tangent): class UniformActuatorRegion(CircularActuatorRegion): - def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): + def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume, comm): thrustBC = self._boundaryConditions[self._thrustBcName] - force = np.outer(thrustBC * cellVolume / totalVolume, -self.thrustVector) + cellThrusts = thrustBC * cellVolume / totalVolume + scaling_constant = self._computeScalingConstant(cellThrusts, thrustBC, comm) + force = np.outer(scaling_constant * cellThrusts, -self.thrustVector) return force - def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): + def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume, comm): heatBC = self._boundaryConditions[self._heatBcName] - heat = heatBC * cellVolume / totalVolume + cellHeats = heatBC * cellVolume / totalVolume + scaling_constant = self._computeScalingConstant(cellHeats, heatBC, comm) - return heat + return cellHeats * scaling_constant class BSplineActuatorRegion(CircularActuatorRegion): @@ -257,13 +274,10 @@ def __init__( ): super().__init__(centerPoint, thrustVector, innerDiameter, outerDiameter, regionDepth, thrust, heat) - # compute a scaling constant such that the integrated thrust equals the total prescribed thrust - scalingConstant = self._computeDistributionScalingConstant(thrustDistribution) - - self._thrustSpline = self._formSpline(thrustDistribution, scalingConstant) - self._tangentSpline = self._formSpline(tangentDistribution, scalingConstant) - self._radialSpline = self._formSpline(radialDistribution, scalingConstant) - self._heatSpline = self._formSpline(heatDistribution, scalingConstant) + self._thrustSpline = interpolate.BSpline(*thrustDistribution) + self._tangentSpline = interpolate.BSpline(*tangentDistribution) + self._radialSpline = interpolate.BSpline(*radialDistribution) + self._heatSpline = interpolate.BSpline(*heatDistribution) def _computeDistributionScalingConstant(self, distribution: Tuple[npt.NDArray, npt.NDArray, float]): n_r = 1000 @@ -294,29 +308,40 @@ def _computeNormalizedRadius(self, distance2axis): normalizedRadius /= self._outerDiameter / 2 - self._innerDiameter / 2 return normalizedRadius - def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): + def computeCellForceVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume, comm): thrustBC = self._boundaryConditions[self._thrustBcName] normalizedRadius = self._computeNormalizedRadius(distance2axis) thrustFactor = thrustBC * cellVolume / totalVolume # add axial contribution (thrust) - force = np.outer(self._thrustSpline(normalizedRadius) * thrustFactor, -self.thrustVector) + cellThrusts = self._thrustSpline(normalizedRadius) * thrustFactor + + # compute a scaling constant such that the summ of the thrust equals the prescribed thrust + scaling_constant = self._computeScalingConstant(cellThrusts, thrustBC, comm) + force = np.outer(scaling_constant * cellThrusts, -self.thrustVector) # add tangential contribution (swirl) - force += np.multiply(tangent.T, np.array([self._tangentSpline(normalizedRadius) * thrustFactor])).T + force += np.multiply( + tangent.T, np.array([scaling_constant * self._tangentSpline(normalizedRadius) * thrustFactor]) + ).T # add radial contribution radius = np.cross(self.thrustVector, tangent) - force += np.multiply(radius.T, np.array([self._radialSpline(normalizedRadius) * 2 * thrustFactor])).T + force += np.multiply( + radius.T, np.array([scaling_constant * self._radialSpline(normalizedRadius) * 2 * thrustFactor]) + ).T return force - def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume): + def computeCellHeatVector(self, distance2axis, distance2plane, tangent, cellVolume, totalVolume, comm): heatBC = self._boundaryConditions[self._heatBcName] normalizedRadius = self._computeNormalizedRadius(distance2axis) - heat = self._heatSpline(normalizedRadius) * heatBC * cellVolume / totalVolume + # compute a scaling constant such that the summ of the heat equals the prescribed heat - return heat + cellHeats = self._heatSpline(normalizedRadius) * heatBC * cellVolume / totalVolume + scaling_constant = self._computeScalingConstant(cellHeats, heatBC, comm) + + return cellHeats * scaling_constant diff --git a/adflow/pyADflow.py b/adflow/pyADflow.py index efbcecd7c..861bdaf11 100644 --- a/adflow/pyADflow.py +++ b/adflow/pyADflow.py @@ -203,7 +203,7 @@ def __init__(self, comm=None, options=None, debug=False, dtype="d"): # had we read in a param file self.adflow.iteration.deforming_grid = True - self._actuatorRegionHandler = ActuatorRegionHandler() + self._actuatorRegionHandler = ActuatorRegionHandler(self.adflow, self.comm) # In order to properly initialize we need to have mach number # and a few other things set. Just create a dummy aeroproblem, @@ -867,9 +867,7 @@ def addActuatorRegion( if relaxEnd < 0 and relaxStart >= 0: raise ValueError("relaxEnd must be given if relaxStart is specified") - self._actuatorRegionHandler.addActuatorRegion( - actuatorRegion, self.adflow, familyName, familyID, relaxStart, relaxEnd - ) + self._actuatorRegionHandler.addActuatorRegion(actuatorRegion, familyName, familyID, relaxStart, relaxEnd) def writeActuatorRegions(self, fileName, outputDir=None): """ @@ -891,7 +889,7 @@ def writeActuatorRegions(self, fileName, outputDir=None): if outputDir is None: outputDir = self.getOption("outputDirectory") - self._actuatorRegionHandler.writeActuatorRegions(self.adflow, fileName, outputDir) + self._actuatorRegionHandler.writeActuatorRegions(fileName, outputDir) def addUserFunction(self, funcName, functions, callBack): """Add a new function to ADflow by combining existing functions in a @@ -3584,7 +3582,7 @@ def _setAeroProblemData(self, aeroProblem, firstCall=False): if not empty: self.adflow.bcdata.setbcdata(nameArray, dataArray, groupArray, 1) - self._actuatorRegionHandler.updateActuatorRegionsBC(AP, self.adflow, self.comm) + self._actuatorRegionHandler.updateActuatorRegionsBC(AP) if not firstCall: self.adflow.initializeflow.updatebcdataalllevels() From c7070518fb2c45d168e6da30c2aff5a9444d3c23 Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Mon, 6 Oct 2025 11:49:40 +0200 Subject: [PATCH 46/49] Use numerically saver comparision --- adflow/actuatorRegion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index aa38ab5e9..d8ca71594 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -49,7 +49,7 @@ def setBCValue(self, bcName, bcValue): self._boundaryConditions[bcName] = bcValue def _computeScalingConstant(self, cellValues, totalValue, comm): - if totalValue == 0: + if np.isclose(totalValue, 0): return 1 computedTotalvalue = comm.allreduce(np.sum(cellValues), op=MPI.SUM) From 3ffa4067d9ec23189a2af563686991b0264ac6c9 Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Mon, 6 Oct 2025 12:48:13 +0200 Subject: [PATCH 47/49] Flip thrust vector in test to point forward --- tests/reg_tests/test_actuator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/reg_tests/test_actuator.py b/tests/reg_tests/test_actuator.py index 375f13f7b..922bb2e54 100644 --- a/tests/reg_tests/test_actuator.py +++ b/tests/reg_tests/test_actuator.py @@ -93,7 +93,7 @@ def setUp(self): actuator_region = UniformActuatorRegion( centerPoint=np.array([-0.38, 0, 0.3]), - thrustVector=np.array([1, 0, 0]), + thrustVector=np.array([-1, 0, 0]), innerDiameter=0.0, outerDiameter=0.354, regionDepth=0.12, From 84e47010e161446b15a5a7b7262aec26aa39333a Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Mon, 6 Oct 2025 16:01:21 +0200 Subject: [PATCH 48/49] Only continue loop after all MPI reductions. Also remove unneeded analytic function --- adflow/actuatorRegion.py | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index d8ca71594..91113c58b 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -49,10 +49,11 @@ def setBCValue(self, bcName, bcValue): self._boundaryConditions[bcName] = bcValue def _computeScalingConstant(self, cellValues, totalValue, comm): - if np.isclose(totalValue, 0): - return 1 - computedTotalvalue = comm.allreduce(np.sum(cellValues), op=MPI.SUM) + + if np.isclose(computedTotalvalue, 0): + return 0.0 + return totalValue / computedTotalvalue @abstractmethod @@ -148,10 +149,6 @@ def updateActuatorRegionsBC(self, aeroproblem: AeroProblem): totalVolume = self._comm.allreduce(np.sum(volume), op=MPI.SUM) - # skip this proc if no cells are active - if actuatorRegion.nLocalCells == 0: - continue - # compute the source terms force = actuatorRegion.computeCellForceVector( distance2axis, distance2plane, tangent, volume, totalVolume, self._comm @@ -160,6 +157,10 @@ def updateActuatorRegionsBC(self, aeroproblem: AeroProblem): distance2axis, distance2plane, tangent, volume, totalVolume, self._comm ) + # skip this proc if no cells are active + if actuatorRegion.nLocalCells == 0: + continue + # apply the source terms in Fortran self._adflow_fortran.actuatorregion.populatebcvalues( actuatorRegion.iRegion, @@ -279,23 +280,6 @@ def __init__( self._radialSpline = interpolate.BSpline(*radialDistribution) self._heatSpline = interpolate.BSpline(*heatDistribution) - def _computeDistributionScalingConstant(self, distribution: Tuple[npt.NDArray, npt.NDArray, float]): - n_r = 1000 - r_inner = self._innerDiameter / 2 - r_outer = self._outerDiameter / 2 - d = interpolate.BSpline(*distribution) - - s = np.linspace(0, 1, n_r) - - r = r_inner + s * (r_outer - r_inner) - dr_ds = r_outer - r_inner - w = 2 * r * dr_ds / (r_outer**2 - r_inner**2) - - integral = np.trapz(d(s) * w, s) - constant = 1 / integral - - return constant - def _formSpline(self, distribution: Tuple[npt.NDArray, npt.NDArray, float], scalingConstant: float): t = distribution[0] c = distribution[1] From b9e823c29be6d7e71c25b1d61a7e9759f5587939 Mon Sep 17 00:00:00 2001 From: David Anderegg Date: Mon, 6 Oct 2025 16:22:07 +0200 Subject: [PATCH 49/49] fix bug where method call was changed but not definition --- adflow/actuatorRegion.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adflow/actuatorRegion.py b/adflow/actuatorRegion.py index 91113c58b..10b588797 100644 --- a/adflow/actuatorRegion.py +++ b/adflow/actuatorRegion.py @@ -169,7 +169,7 @@ def updateActuatorRegionsBC(self, aeroproblem: AeroProblem): heat.T, ) - def writeActuatorRegions(self, adflow_fortran: ModuleType, fileName: str, outputDir: str): + def writeActuatorRegions(self, fileName: str, outputDir: str): # Join to get the actual filename root fileName = os.path.join(outputDir, fileName) @@ -178,7 +178,7 @@ def writeActuatorRegions(self, adflow_fortran: ModuleType, fileName: str, output fileName += ".plt" # just call the underlying fortran routine - adflow_fortran.actuatorregion.writeactuatorregions(fileName) + self._adflow_fortran.actuatorregion.writeactuatorregions(fileName) class CircularActuatorRegion(AbstractActuatorRegion):