Index: palm/trunk/SOURCE/CURRENT_MODIFICATIONS
===================================================================
--- palm/trunk/SOURCE/CURRENT_MODIFICATIONS	(revision 143)
+++ palm/trunk/SOURCE/CURRENT_MODIFICATIONS	(revision 144)
@@ -15,5 +15,7 @@
 necessary for the current subdomain.
 
-check_open, read_var_list, read_3d_binary, write_3d_binary
+User-defined spectra.
+
+calc_spectra, check_open, data_output_spectra, netcdf, read_var_list, read_3d_binary, user_interface, write_3d_binary
 
 
@@ -38,5 +40,6 @@
 NetCDF files newly created by restart files (no append of existing files!)
 contained uneccessary time levels. (read_3d_binary, write_3d_binary)
+Bugfix: extra '*' removed in user_statistics sample code (user_interface)
 
-flow_statistics, plant_canopy_model, read_3d_binary, write_3d_binary
+flow_statistics, plant_canopy_model, read_3d_binary, user_interface, write_3d_binary
 
Index: palm/trunk/SOURCE/calc_spectra.f90
===================================================================
--- palm/trunk/SOURCE/calc_spectra.f90	(revision 143)
+++ palm/trunk/SOURCE/calc_spectra.f90	(revision 144)
@@ -4,5 +4,5 @@
 ! Actual revisions:
 ! -----------------
-! 
+! user-defined spectra
 !
 ! Former revisions:
@@ -180,6 +180,10 @@
        
     CASE DEFAULT
-       PRINT*, '+++ preprocess_spectra: Spectra of ', &
-               TRIM( data_output_sp(m) ), ' can not be calculated'
+!
+!--    The DEFAULT case is reached either if the parameter data_output_sp(m)
+!--    contains a wrong character string or if the user has coded a special
+!--    case in the user interface. There, the subroutine user_spectra 
+!--    checks which of these two conditions applies.
+       CALL user_spectra( 'preprocess', m, pr )
           
     END SELECT
Index: palm/trunk/SOURCE/data_output_spectra.f90
===================================================================
--- palm/trunk/SOURCE/data_output_spectra.f90	(revision 143)
+++ palm/trunk/SOURCE/data_output_spectra.f90	(revision 144)
@@ -4,5 +4,5 @@
 ! Actual revisions:
 ! -----------------
-! 
+! user-defined spectra
 !
 ! Former revisions:
@@ -117,6 +117,11 @@
 
              CASE DEFAULT
-                PRINT*, '+++ data_output_spectra: Spectra of ', &
-                             TRIM( data_output_sp(m) ), ' are not defined'
+!
+!--             The DEFAULT case is reached either if the parameter 
+!--             data_output_sp(m) contains a wrong character string or if the 
+!--             user has coded a special case in the user interface. There, the 
+!--             subroutine user_spectra checks which of these two conditions 
+!--             applies.
+                CALL user_spectra( 'data_output', m, pr )
 
           END SELECT
Index: palm/trunk/SOURCE/netcdf.f90
===================================================================
--- palm/trunk/SOURCE/netcdf.f90	(revision 143)
+++ palm/trunk/SOURCE/netcdf.f90	(revision 144)
@@ -7,5 +7,5 @@
 ! Current revisions:
 ! ------------------
-! 
+! user-defined spectra
 !
 ! Former revisions:
@@ -2867,4 +2867,28 @@
           i = 1
           DO WHILE ( data_output_sp(i) /= ' '  .AND.  i <= 10 )
+!
+!--          First check for the vertical grid
+             found = .TRUE.
+             SELECT CASE ( data_output_sp(i) )
+!
+!--             Most variables are defined on the zu levels
+                CASE ( 'e', 'p', 'pc', 'pr', 'pt', 'q', 'ql', 'ql_c', 'ql_v', &
+                       'ql_vp', 'qv', 'rho', 's', 'sa', 'u', 'v', 'vpt' )
+
+                   grid_z = 'zu'
+!
+!--             zw levels
+                CASE ( 'w' )
+
+                   grid_z = 'zw'
+
+                CASE DEFAULT
+!
+!--                Check for user-defined quantities (found, grid_x and grid_y
+!--                are dummies)
+                   CALL user_define_netcdf_grid( data_output_sp(i), found,  &
+                                                 grid_x, grid_y, grid_z )
+
+             END SELECT
 
              IF ( INDEX( spectra_direction(i), 'x' ) /= 0 )  THEN
@@ -2873,5 +2897,6 @@
 !--             Define the variable
                 netcdf_var_name = TRIM( data_output_sp(i) ) // '_x'
-                IF ( data_output_sp(i) == 'w' )  THEN
+                CALL clean_netcdf_varname( netcdf_var_name )
+                IF ( TRIM( grid_z ) == 'zw' )  THEN
                    nc_stat = NF90_DEF_VAR( id_set_sp, netcdf_var_name,      &
                                            nc_precision(7), (/ id_dim_x_sp, &
@@ -2903,5 +2928,6 @@
 !--             Define the variable
                 netcdf_var_name = TRIM( data_output_sp(i) ) // '_y'
-                IF ( data_output_sp(i) == 'w' )  THEN
+                CALL clean_netcdf_varname( netcdf_var_name )
+                IF ( TRIM( grid_z ) == 'zw' )  THEN
                    nc_stat = NF90_DEF_VAR( id_set_sp, netcdf_var_name,      &
                                            nc_precision(7), (/ id_dim_y_sp, &
Index: palm/trunk/SOURCE/user_interface.f90
===================================================================
--- palm/trunk/SOURCE/user_interface.f90	(revision 143)
+++ palm/trunk/SOURCE/user_interface.f90	(revision 144)
@@ -4,5 +4,5 @@
 ! Actual revisions:
 ! -----------------
-! 
+! new subroutine user_spectra
 !
 ! Former revisions:
@@ -56,4 +56,5 @@
 !-- Sample for user-defined output
 !    REAL, DIMENSION(:,:,:), ALLOCATABLE ::  u2, u2_av
+!    REAL, DIMENSION(:,:,:), ALLOCATABLE ::  ustvst
 
     SAVE
@@ -198,4 +199,5 @@
 !-- Sample for user-defined output
 !    ALLOCATE( u2(nzb:nzt+1,nys-1:nyn+1,nxl-1:nxr+1) )
+!    ALLOCATE( ustvst(nzb:nzt+1,nys-1:nyn+1,nxl-1:nxr+1) )
 !
 !    IF ( initializing_actions == 'read_restart_data' )  THEN
@@ -456,4 +458,13 @@
 !                ENDDO
 !             ENDDO
+!             DO  i = nxl-1, nxr+1
+!                DO  j = nys-1, nyn+1
+!                   DO  k = nzb, nzt+1
+!                      ustvst(k,j,i) =  &
+!                         ( 0.5 * ( u(k,j,i) + u(k,j,i+1) ) - hom(k,1,1,0) ) * &
+!                         ( 0.5 * ( v(k,j,i) + v(k,j+1,i) ) - hom(k,1,2,0) )
+!                   ENDDO
+!                ENDDO
+!             ENDDO
 
 
@@ -561,4 +572,74 @@
  END MODULE user_actions_mod
 
+
+
+ SUBROUTINE user_spectra( mode, m, pr )
+
+!------------------------------------------------------------------------------!
+!
+! Description:
+! ------------
+! Calculation of user-defined spectra.
+! See section 3.5.4 on how to define, calculate, and output user defined
+! quantities.
+!------------------------------------------------------------------------------!
+
+    USE arrays_3d
+    USE indices
+    USE spectrum
+    USE statistics
+    USE user
+
+    IMPLICIT NONE
+
+    CHARACTER (LEN=*) ::  mode
+
+    INTEGER ::  i, j, k, m, pr
+
+
+!
+!-- Sample on how to calculate spectra of user-defined quantities. 
+!-- Each quantity is identified by the corresponding user profile index
+!-- "pr_palm+#" where "#" is an integer starting from 1. These
+!-- user-profile-numbers must also be assigned to the respective strings
+!-- given by data_output_pr_user in routine user_check_data_output_pr.
+    IF ( mode == 'preprocess' )  THEN
+
+       SELECT CASE ( TRIM( data_output_sp(m) ) )
+          
+          CASE ( 'u', 'v', 'w', 'pt', 'q' )
+!--          Not allowed here since these are the standard quantities used in 
+!--          preprocess_spectra.
+       
+!          CASE ( 'u*v*' )
+!             pr = pr_palm+1
+!             d(nzb+1:nzt,nys:nyn,nxl:nxr) = ustvst(nzb+1:nzt,nys:nyn,nxl:nxr)
+       
+          CASE DEFAULT
+             PRINT*, '+++ user_spectra/preprocess: Spectra of ', &
+                  TRIM( data_output_sp(m) ), ' can not be calculated'
+          
+       END SELECT
+
+    ELSEIF ( mode == 'data_output' )  THEN
+
+       SELECT CASE ( TRIM( data_output_sp(m) ) )
+
+          CASE ( 'u', 'v', 'w', 'pt', 'q' )
+!--          Not allowed here since these are the standard quantities used in 
+!--          data_output_spectra.
+
+!          CASE ( 'u*v*' )
+!             pr = 6
+
+          CASE DEFAULT
+             PRINT*, '+++ user_spectra/data_output: Spectra of ', &
+                          TRIM( data_output_sp(m) ), ' are not defined'
+
+          END SELECT
+
+    ENDIF
+
+ END SUBROUTINE user_spectra
 
 
@@ -600,5 +681,5 @@
 !       DO  i = nxl, nxr
 !          DO  j = nys, nyn
-!             DO  k = nzb_s_outer(j,i)+1, nzt
+!             DO  k = nzb_s_inner(j,i)+1, nzt
 !!
 !!--             Sample on how to calculate the profile of the resolved-scale
@@ -606,5 +687,5 @@
 !                sums_l(k,pr_palm+1,tn) = sums_l(k,pr_palm+1,tn) +           &
 !                      ( 0.5 * ( u(k,j,i) + u(k,j,i+1) ) - hom(k,1,1,sr) ) * &
-!                      ( 0.5 * ( v(k,j,i) + v(k,j+1,i) ) - hom(k,1,2,sr) ) * &
+!                      ( 0.5 * ( v(k,j,i) + v(k,j+1,i) ) - hom(k,1,2,sr) )   &
 !                                                 * rmask(j,i,sr)
 !!
@@ -796,4 +877,7 @@
 !--    Uncomment and extend the following lines, if necessary
 !       CASE ( 'u2' )
+!          unit = 'm2/s2'
+!
+!       CASE ( 'u*v*' )
 !          unit = 'm2/s2'
 !
@@ -890,4 +974,9 @@
 !       CASE ( 'u2', 'u2_xy', 'u2_xz', 'u2_yz' )
 !          grid_x = 'xu'
+!          grid_y = 'y'
+!          grid_z = 'zu'
+
+!       CASE ( 'u*v*', 'u*v*_xy', 'u*v*_xz', 'u*v*_yz' )
+!          grid_x = 'x'
 !          grid_y = 'y'
 !          grid_z = 'zu'
