Adds a pressure-balanced warm bubble perturbation.
The potential temperature perturbation has a cos^2 profile:
theta'(x,y,z) = dtheta * cos^2(pir / (2r0)) for r <= r0 theta'(x,y,z) = 0 for r > r0
where r = sqrt((x-x0)^2 + (y-y0)^2 + (z-z0)^2).
To maintain pressure balance (p unchanged), the density is adjusted while rho*theta remains constant:
theta_new = theta_old + theta' rho_new = rho_old * theta_old / theta_new (rhotheta)_new = rho_old * theta_old = (rhotheta)_old
The buoyancy force arises from the density deficit in the gravitational source term -rho*g.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ESAtmo3D_t), | intent(inout) | :: | this | |||
| real(kind=prec), | intent(in) | :: | dtheta | |||
| real(kind=prec), | intent(in) | :: | r0 | |||
| real(kind=prec), | intent(in) | :: | x0 | |||
| real(kind=prec), | intent(in) | :: | y0 | |||
| real(kind=prec), | intent(in) | :: | z0 |
subroutine AddThermalBubble_ESAtmo3D_t(this,dtheta,r0,x0,y0,z0)
!! Adds a pressure-balanced warm bubble perturbation.
!!
!! The potential temperature perturbation has a cos^2 profile:
!!
!! theta'(x,y,z) = dtheta * cos^2(pi*r / (2*r0)) for r <= r0
!! theta'(x,y,z) = 0 for r > r0
!!
!! where r = sqrt((x-x0)^2 + (y-y0)^2 + (z-z0)^2).
!!
!! To maintain pressure balance (p unchanged), the density is
!! adjusted while rho*theta remains constant:
!!
!! theta_new = theta_old + theta'
!! rho_new = rho_old * theta_old / theta_new
!! (rho*theta)_new = rho_old * theta_old = (rho*theta)_old
!!
!! The buoyancy force arises from the density deficit in the
!! gravitational source term -rho*g.
implicit none
class(ESAtmo3D_t),intent(inout) :: this
real(prec),intent(in) :: dtheta ! Perturbation amplitude [K]
real(prec),intent(in) :: r0 ! Bubble radius [m]
real(prec),intent(in) :: x0,y0,z0 ! Bubble center [m]
! Local
integer :: i,j,k,iEl
real(prec) :: x,y,z,r,rho_old,theta_old,theta_new,thetap
print*,__FILE__," : Adding thermal bubble perturbation"
print*,__FILE__," : dtheta = ",dtheta
print*,__FILE__," : r0 = ",r0
print*,__FILE__," : center = ",x0,y0,z0
do concurrent(i=1:this%solution%N+1,j=1:this%solution%N+1, &
k=1:this%solution%N+1,iEl=1:this%mesh%nElem)
x = this%geometry%x%interior(i,j,k,iEl,1,1)-x0
y = this%geometry%x%interior(i,j,k,iEl,1,2)-y0
z = this%geometry%x%interior(i,j,k,iEl,1,3)-z0
r = sqrt(x*x+y*y+z*z)
if(r <= r0) then
rho_old = this%solution%interior(i,j,k,iEl,1)
theta_old = this%solution%interior(i,j,k,iEl,5)/rho_old
thetap = dtheta*cos(pi*r/(2.0_prec*r0))**2
theta_new = theta_old+thetap
! Adjust density to maintain pressure balance: rho*theta = const
this%solution%interior(i,j,k,iEl,1) = rho_old*theta_old/theta_new
! rho*theta is unchanged (pressure-balanced perturbation)
endif
enddo
call this%ReportMetrics()
call this%solution%UpdateDevice()
endsubroutine AddThermalBubble_ESAtmo3D_t