Changeset 4771


Ignore:
Timestamp:
Nov 4, 2020 1:12:46 PM (4 years ago)
Author:
hellstea
Message:

Canopy-restricted anterpolation introduced

Location:
palm/trunk/SOURCE
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • palm/trunk/SOURCE/pmc_handle_communicator_mod.f90

    r4650 r4771  
    2525! -----------------
    2626! $Id$
     27! Canopy-restricted anterpolation introduced. New namelist parameter anterpolation_starting_height
     28! introduced for controlling canopy-restricted anterpolation.
     29!
     30! 4650 2020-08-25 14:35:50Z raasch
    2731! bugfix for r4649
    2832!
     
    138142!--------------------------------------------------------------------------------------------------!
    139143 SUBROUTINE pmc_init_model( comm, nesting_datatransfer_mode, nesting_mode,                         &
    140                             anterpolation_buffer_width, pmc_status )
     144                            anterpolation_buffer_width, anterpolation_starting_height, pmc_status )
    141145
    142146    USE control_parameters,                                                                        &
     
    155159    INTEGER, INTENT(INOUT) ::  pmc_status                  !<
    156160
     161    REAL(wp), INTENT(INOUT) ::  anterpolation_starting_height  !< steering parameter for canopy restricted anterpolation
     162   
    157163    INTEGER ::  childcount     !<
    158164    INTEGER ::  i              !<
     
    180186
    181187       CALL read_coupling_layout( nesting_datatransfer_mode, nesting_mode,                         &
    182                                   anterpolation_buffer_width, pmc_status )
     188            anterpolation_buffer_width, anterpolation_starting_height,                             &
     189            pmc_status )
    183190
    184191       IF ( pmc_status /= pmc_no_namelist_found  .AND.                                             &
     
    252259                    MPI_COMM_WORLD, istat )
    253260    CALL MPI_BCAST( anterpolation_buffer_width, 1, MPI_INT, 0, MPI_COMM_WORLD, istat )
     261    CALL MPI_BCAST( anterpolation_starting_height, 1, MPI_REAL, 0, MPI_COMM_WORLD, istat )
    254262!
    255263!-- Assign global MPI processes to individual models by setting the couple id
     
    422430!--------------------------------------------------------------------------------------------------!
    423431 SUBROUTINE read_coupling_layout( nesting_datatransfer_mode, nesting_mode,                         &
    424                                   anterpolation_buffer_width, pmc_status )
     432                                  anterpolation_buffer_width, anterpolation_starting_height,       &
     433                                  pmc_status )
    425434
    426435    IMPLICIT NONE
     
    431440    INTEGER, INTENT(INOUT)      ::  anterpolation_buffer_width  !< Boundary buffer width for anterpolation
    432441    INTEGER(iwp), INTENT(INOUT) ::  pmc_status                  !<
     442
     443    REAL(wp), INTENT(INOUT) ::  anterpolation_starting_height   !< steering parameter for canopy restricted anterpolation
    433444
    434445    INTEGER(iwp) ::  bad_llcorner  !<
     
    441452                                   nesting_datatransfer_mode,                                      &
    442453                                   nesting_mode,                                                   &
    443                                    anterpolation_buffer_width
     454                                   anterpolation_buffer_width,                                     &
     455                                   anterpolation_starting_height
    444456
    445457!
  • palm/trunk/SOURCE/pmc_interface_mod.f90

    r4745 r4771  
    2525! -----------------
    2626! $Id$
     27! Canopy-restricted anterpolation introduced. New namelist parameter anterpolation_starting_height
     28! introduced for controlling canopy-restricted anterpolation.
     29!
     30! 4745 2020-10-15 16:37:13Z suehring
    2731! Adjustement of face-area calculation to 3D-topographies
    2832!
     
    453457    INTEGER(iwp), SAVE ::  anterpolation_buffer_width = 2  !< Boundary buffer width for anterpolation
    454458
     459    REAL(wp), SAVE ::  anterpolation_starting_height = 9999999.9_wp  !< steering parameter for canopy restricted anterpolation
     460
    455461    LOGICAL, SAVE ::  nested_run = .FALSE.        !< general switch
    456462    LOGICAL, SAVE ::  rans_mode_parent = .FALSE.  !< mode of parent model (.F. - LES mode, .T. - RANS mode)
     
    463469!
    464470!-- Children's parent-grid arrays
     471    INTEGER(iwp), SAVE, DIMENSION(:,:), ALLOCATABLE :: kpb_anterp  !< Lower limit of kp in anterpolation
    465472    INTEGER(iwp), SAVE, DIMENSION(5), PUBLIC ::  parent_bound  !< subdomain index bounds for children's parent-grid arrays
    466473
     
    702709
    703710    CALL pmc_init_model( world_comm, nesting_datatransfer_mode, nesting_mode,                      &
    704                          anterpolation_buffer_width, pmc_status )
     711                         anterpolation_buffer_width, anterpolation_starting_height, pmc_status )
    705712
    706713    IF ( pmc_status == pmc_no_namelist_found )  THEN
     
    15071514!--    Compute surface areas of the nest-boundary faces
    15081515       CALL pmci_compute_face_areas
    1509 
     1516!       
     1517!--    Compute anterpolation lower kp-index bounds if necessary
     1518       CALL pmci_compute_kpb_anterp
    15101519    ENDIF
    15111520
     
    24382447
    24392448 END SUBROUTINE pmci_compute_face_areas
     2449
     2450
     2451!--------------------------------------------------------------------------------------------------!
     2452! Description:
     2453! ------------
     2454!> Define the anterpolation starting kp-indices for all jp,ip based on the obstacle-canopy
     2455!> topograhy for canopy-restricted anterpolation. Note that this is based on the child terrain
     2456!> topography information since it is difficult to access the parent topography information
     2457!> from the child. This means that these topographies are assumed to be close to each other.
     2458!--------------------------------------------------------------------------------------------------!
     2459 SUBROUTINE pmci_compute_kpb_anterp
     2460
     2461    INTEGER(iwp) ::  ic                     !< Child-grid index in the x-direction
     2462    INTEGER(iwp) ::  ip                     !< Parent-grid index in the x-direction
     2463    INTEGER(iwp) ::  jc                     !< Child-grid index in the y-direction
     2464    INTEGER(iwp) ::  jp                     !< Parent-grid index in the y-direction
     2465    INTEGER(iwp) ::  terrain_surf_k_child   !< Local terrain height k index in the child grid
     2466    INTEGER(iwp) ::  terrain_surf_k_parent  !< Local terrain height k index in the parent grid
     2467
     2468   
     2469    ALLOCATE( kpb_anterp(jps:jpn,ipl:ipr) )
     2470    kpb_anterp(jps:jpn,ipl:ipr) = 0
     2471   
     2472    IF ( nesting_mode /= 'one-way'  .AND.  topography /= 'flat' )  THEN
     2473!     
     2474!--    Check if the value was given by user or not
     2475       IF ( anterpolation_starting_height > 9000000.0_wp )  THEN
     2476!         
     2477!--       No value was given by user, compute a default value first.
     2478          CALL default_anterpolation_starting_height( 99 )
     2479       ENDIF
     2480
     2481       DO  ip = ipl, ipr
     2482          DO  jp = jps, jpn           
     2483             terrain_surf_k_parent = 0
     2484             DO  ic = iflo(ip), ifuo(ip)
     2485                DO  jc = jflo(jp), jfuo(jp)
     2486                   terrain_surf_k_child = MINLOC(                                                   &
     2487                        MERGE( 1, 0, BTEST( wall_flags_total_0(:,jc,ic), 5 ) ), DIM = 1 ) - 1
     2488                   terrain_surf_k_parent = MAX( terrain_surf_k_child, terrain_surf_k_parent )
     2489                ENDDO
     2490             ENDDO
     2491             terrain_surf_k_parent = NINT( terrain_surf_k_parent / REAL( kgsr, wp ) )
     2492             kpb_anterp(jp,ip) = terrain_surf_k_parent + NINT( anterpolation_starting_height / pg%dz )
     2493          ENDDO
     2494       ENDDO
     2495
     2496    ENDIF
     2497
     2498 END SUBROUTINE pmci_compute_kpb_anterp
     2499
     2500
     2501!--------------------------------------------------------------------------------------------------!
     2502! Description:
     2503! ------------
     2504!> Compute a default value for the anterpolation_starting_height for the canopy-restricted
     2505!> anterpolation. The default value is based on a given percentile of the child building height
     2506!> distribution. This operation is based on the child-grid information.
     2507!--------------------------------------------------------------------------------------------------!
     2508 SUBROUTINE default_anterpolation_starting_height( percentile_level )
     2509   
     2510    INTEGER(iwp), INTENT(IN) ::  percentile_level  !< Selected percentile level (1,...,99)
     2511
     2512    INTEGER(iwp) ::  ic                            !< Child-grid index in the x-direction
     2513    INTEGER(iwp) ::  ierr                          !< MPI-error code
     2514    INTEGER(iwp) ::  im                            !< Grid index in the x-direction of the currently
     2515                                                   !< globally highest building node
     2516    INTEGER(iwp) ::  jc                            !< Child-grid index in the y-direction
     2517    INTEGER(iwp), DIMENSION(2) :: ji_maxloc        !< jc and ic indices of the local maximum height
     2518    INTEGER(iwp) ::  jm                            !< Grid index in the y-direction of the currently
     2519                                                   !< globally highest building node
     2520    INTEGER(iwp) ::  num_building_nodes            !< Global number of jc,ic-nodes under buildings
     2521    INTEGER(iwp) ::  num_building_nodes_l          !< Local number of jc,ic-nodes under buildings
     2522    INTEGER(iwp) ::  num_highest_nodes             !< The number of highest building nodes above the
     2523                                                   !< percentile value
     2524    INTEGER(iwp) ::  n                             !< Running index for the sorting loop
     2525    INTEGER(iwp) ::  pid_highest                   !< Process id of the process where the currently
     2526                                                   !< highest building node was found.
     2527    INTEGER(iwp) ::  terrain_surf_k                !< Local terrain height k index in the child grid
     2528                                                 
     2529    REAL(wp) ::  global_currently_highest          !< Globally highest building node currently in the
     2530                                                   !< search loop
     2531    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  building_height  !< Temporary array for buiding heights
     2532    REAL(wp), DIMENSION(:), ALLOCATABLE ::  max_height         !< Maximum buiding heights of each
     2533                                                               !< process
     2534    REAL(wp), DIMENSION(:), ALLOCATABLE ::  max_height_l       !< max_height_l( myid ) is the local
     2535                                                               !< maximum buiding height of the
     2536                                                               !< current process while the other
     2537                                                               !< elements are zeroes
     2538   
     2539    ALLOCATE( building_height(nys:nyn,nxl:nxr) )
     2540!
     2541!-- Find the building heights and temporarily store them in building_height(nys:nyn,nxl:nxr).   
     2542!-- Also find the number of nodes occupied by buildings
     2543    num_building_nodes_l = 0
     2544    num_building_nodes   = 0
     2545    DO  ic = nxl, nxr
     2546       DO  jc = nys, nyn
     2547          terrain_surf_k  = MINLOC( MERGE( 1, 0, BTEST( wall_flags_total_0(:,jc,ic), 5 ) ),         &
     2548                                    DIM = 1 ) - 1
     2549          IF ( topo_top_ind(jc,ic,5) > terrain_surf_k )  THEN                     
     2550             building_height(jc,ic) = dz(1) * ( topo_top_ind(jc,ic,5) - terrain_surf_k + 1 )
     2551             num_building_nodes_l = num_building_nodes_l + 1
     2552          ENDIF
     2553       ENDDO
     2554    ENDDO
     2555   
     2556    CALL MPI_ALLREDUCE( num_building_nodes_l, num_building_nodes, 1, MPI_INT, MPI_SUM, comm2d, ierr )
     2557   
     2558    num_highest_nodes = MAX( 1, NINT( num_building_nodes * ( 100 - percentile_level ) / 100.0_wp ) )
     2559!   
     2560!-- Find global percentile value
     2561    ALLOCATE( max_height_l(0:numprocs-1) )
     2562    ALLOCATE( max_height(0:numprocs-1) )
     2563    max_height_l = 0.0_wp
     2564!
     2565!-- Search loop for the num_highest_nodes highest nodes globally.
     2566    DO  n = 1, num_highest_nodes
     2567       max_height = 0.0_wp
     2568       max_height_l(myid) = MAXVAL( building_height )
     2569       CALL MPI_ALLREDUCE( max_height_l, max_height, numprocs, MPI_REAL, MPI_SUM, comm2d, ierr )
     2570       global_currently_highest = MAXVAL( max_height )
     2571       pid_highest = MAXLOC( max_height, DIM = 1 ) - 1
     2572!       
     2573!--    Set the globally currently highest height to zero in order to find the next
     2574!--    highest node in the next loop cycle.
     2575       IF ( pid_highest == myid )  THEN
     2576          ji_maxloc = MAXLOC( building_height )
     2577          jm = ji_maxloc(1) - 1 + nys
     2578          im = ji_maxloc(2) - 1 + nxl
     2579          building_height(jm,im) = 0.0_wp
     2580       ENDIF
     2581    ENDDO
     2582!
     2583!-- Now after the search-loop, global_currently_highest is the desired percentile
     2584!-- value. Add two parent-grid dz in order to create appropriate clearance above the
     2585!-- roofs in cases of evenly distributed building height such as simple
     2586!-- cuboid-array test cases.
     2587    anterpolation_starting_height = global_currently_highest + 2.0_wp * pg%dz
     2588
     2589    WRITE( 9, * )
     2590    WRITE( 9, "('A default value is defined and set for anterpolation_starting_height = ',          &
     2591                f4.1, ' m.' )" )  anterpolation_starting_height
     2592    WRITE( 9, * )
     2593
     2594    DEALLOCATE( max_height_l )
     2595    DEALLOCATE( max_height )
     2596    DEALLOCATE( building_height )
     2597   
     2598 END SUBROUTINE default_anterpolation_starting_height
     2599
    24402600#endif
    24412601
     
    48154975    INTEGER(iwp) ::  kc              !< Running index z-direction - child grid
    48164976    INTEGER(iwp) ::  kp              !< Running index z-direction - parent grid
    4817     INTEGER(iwp) ::  kpb_anterp = 0  !< Bottom boundary index for anterpolation along z
    48184977    INTEGER(iwp) ::  kpt_anterp      !< Top boundary index for anterpolation along z
    48194978    INTEGER(iwp) ::  var_flag        !< bit number used to flag topography on respective grid
     
    48344993    jps_anterp = jps
    48354994    jpn_anterp = jpn
    4836     kpb_anterp = 0
     4995!
     4996!-- kpb_anterp is a function of jp and ip and it is set in the initialization phase in
     4997!-- pmci_compute_kpb_anterp.
    48374998    kpt_anterp = kct - 1 - anterpolation_buffer_width
    48384999
     
    48625023       DO  jp = jps_anterp, jpn_anterp
    48635024!
    4864 !--       For simplicity anterpolate within buildings and under elevated terrain too
    4865           DO  kp = kpb_anterp, kpt_anterp
     5025!--       If the user has set anterpolation_starting_height less than the canopy height, the
     5026!--       anterpolation is made also within buildings for simplicity, and even under elevated
     5027!--       terrain if anterpolation_starting_height is set smaller than terrain height.
     5028          DO  kp = kpb_anterp(jp,ip), kpt_anterp
    48665029             cellsum = 0.0_wp
    48675030             DO  ic = ifl(ip), ifu(ip)
Note: See TracChangeset for help on using the changeset viewer.