AddThermalBubble_ESAtmo3D_t Subroutine

public 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(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.

Arguments

TypeIntentOptionalAttributesName
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

Contents


Source Code

  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