Changeset 4500 for palm/trunk/SOURCE/surface_data_output_mod.f90
- Timestamp:
- Apr 17, 2020 10:12:45 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
palm/trunk/SOURCE/surface_data_output_mod.f90
r4495 r4500 25 25 ! ----------------- 26 26 ! $Id$ 27 ! - Correct output of ground/wall heat flux at USM surfaces 28 ! - Add conversion factor to heat and momentum-flux output 29 ! 30 ! 4495 2020-04-13 20:11:20Z raasch 27 31 ! restart data handling with MPI-IO added 28 32 ! … … 106 110 USE kinds 107 111 108 USE arrays_3d, & 109 ONLY: zu, zw 110 111 USE control_parameters, & 112 ONLY: coupling_char, data_output_during_spinup, end_time, & 113 message_string, restart_data_format_output, run_description_header, simulated_time_at_begin, & 112 USE arrays_3d, & 113 ONLY: heatflux_output_conversion, & 114 momentumflux_output_conversion, & 115 waterflux_output_conversion, & 116 zu, & 117 zw 118 119 USE control_parameters, & 120 ONLY: coupling_char, data_output_during_spinup, end_time, & 121 message_string, & 122 restart_data_format_output, run_description_header, simulated_time_at_begin, & 114 123 spinup_time, surface_output 115 124 … … 137 146 ONLY: rrd_mpi_io, wrd_mpi_io 138 147 139 USE surface_mod, & 140 ONLY: surf_def_h, surf_def_v, surf_lsm_h, surf_lsm_v, & 141 surf_usm_h, surf_usm_v 148 USE surface_mod, & 149 ONLY: ind_pav_green, & 150 ind_veg_wall, & 151 ind_wat_win, & 152 surf_def_h, & 153 surf_def_v, & 154 surf_lsm_h, & 155 surf_lsm_v, & 156 surf_usm_h, & 157 surf_usm_v 142 158 143 159 IMPLICIT NONE … … 1432 1448 INTEGER(iwp) :: av !< id indicating average or non-average data output 1433 1449 INTEGER(iwp) :: i !< loop index 1450 INTEGER(iwp) :: l !< running index for surface orientation 1451 INTEGER(iwp) :: m !< running index for surface elements 1434 1452 INTEGER(iwp) :: n_out !< counter variables for surface output 1435 1453 … … 1957 1975 surf_def_v(3)%usws, & 1958 1976 surf_lsm_v(3)%usws, & 1959 surf_usm_v(3)%usws ) 1977 surf_usm_v(3)%usws, & 1978 momentumflux_output_conversion ) 1960 1979 ELSE 1961 1980 ! … … 1986 2005 surf_def_v(3)%vsws, & 1987 2006 surf_lsm_v(3)%vsws, & 1988 surf_usm_v(3)%vsws ) 2007 surf_usm_v(3)%vsws, & 2008 momentumflux_output_conversion ) 1989 2009 ELSE 1990 2010 ! … … 2015 2035 surf_def_v(3)%shf, & 2016 2036 surf_lsm_v(3)%shf, & 2017 surf_usm_v(3)%shf ) 2037 surf_usm_v(3)%shf, & 2038 heatflux_output_conversion ) 2018 2039 ELSE 2019 2040 ! … … 2043 2064 surf_def_v(3)%qsws, & 2044 2065 surf_lsm_v(3)%qsws, & 2045 surf_usm_v(3)%qsws ) 2066 surf_usm_v(3)%qsws, & 2067 waterflux_output_conversion ) 2046 2068 ELSE 2047 2069 ! … … 2463 2485 !-- Output of instantaneous data 2464 2486 IF ( av == 0 ) THEN 2487 ! 2488 !-- Sum up ground / wall heat flux. Note, for urban surfaces the 2489 !-- wall heat flux is aggregated from the different green, window 2490 !-- and wall tiles. 2491 DO m = 1, surf_usm_h%ns 2492 surf_usm_h%ghf(m) = surf_usm_h%frac(m,ind_veg_wall) & 2493 * surf_usm_h%wghf_eb(m) + & 2494 surf_usm_h%frac(m,ind_pav_green) & 2495 * surf_usm_h%wghf_eb_green(m) + & 2496 surf_usm_h%frac(m,ind_wat_win) & 2497 * surf_usm_h%wghf_eb_window(m) 2498 ENDDO 2499 DO l = 0, 3 2500 DO m = 1, surf_usm_v(l)%ns 2501 surf_usm_v(l)%ghf(m) = surf_usm_v(l)%frac(m,ind_veg_wall) & 2502 * surf_usm_v(l)%wghf_eb(m) + & 2503 surf_usm_v(l)%frac(m,ind_pav_green) & 2504 * surf_usm_v(l)%wghf_eb_green(m) + & 2505 surf_usm_v(l)%frac(m,ind_wat_win) & 2506 * surf_usm_v(l)%wghf_eb_window(m) 2507 ENDDO 2508 ENDDO 2509 2465 2510 CALL surface_data_output_collect( surf_def_h(0)%ghf, & 2466 2511 surf_def_h(1)%ghf, & … … 2479 2524 surf_lsm_v(3)%ghf, & 2480 2525 surf_usm_v(3)%ghf ) 2481 2526 ELSE 2482 2527 ! 2483 2528 !-- Output of averaged data … … 2955 3000 CHARACTER(LEN=100) :: trimvar !< dummy variable for current output variable 2956 3001 3002 INTEGER(iwp) :: l !< running index for surface orientation 3003 INTEGER(iwp) :: m !< running index for surface elements 2957 3004 INTEGER(iwp) :: n_out !< counter variables for surface output 2958 3005 … … 3251 3298 surf_def_v(3)%usws, & 3252 3299 surf_lsm_v(3)%usws, & 3253 surf_usm_v(3)%usws, n_out ) 3300 surf_usm_v(3)%usws, n_out, & 3301 momentumflux_output_conversion ) 3254 3302 3255 3303 CASE ( 'vsws' ) … … 3269 3317 surf_def_v(3)%vsws, & 3270 3318 surf_lsm_v(3)%vsws, & 3271 surf_usm_v(3)%vsws, n_out ) 3319 surf_usm_v(3)%vsws, n_out, & 3320 momentumflux_output_conversion ) 3272 3321 3273 3322 CASE ( 'shf' ) … … 3287 3336 surf_def_v(3)%shf, & 3288 3337 surf_lsm_v(3)%shf, & 3289 surf_usm_v(3)%shf, n_out ) 3338 surf_usm_v(3)%shf, n_out, & 3339 heatflux_output_conversion ) 3290 3340 3291 3341 CASE ( 'qsws' ) … … 3305 3355 surf_def_v(3)%qsws, & 3306 3356 surf_lsm_v(3)%qsws, & 3307 surf_usm_v(3)%qsws, n_out ) 3357 surf_usm_v(3)%qsws, n_out, & 3358 waterflux_output_conversion ) 3308 3359 3309 3360 CASE ( 'ssws' ) … … 3561 3612 3562 3613 CASE ( 'ghf' ) 3614 ! 3615 !-- Sum up ground / wall heat flux. Note, for urban surfaces the 3616 !-- wall heat flux is aggregated from the different green, window 3617 !-- and wall tiles. 3618 DO m = 1, surf_usm_h%ns 3619 surf_usm_h%ghf(m) = surf_usm_h%frac(m,ind_veg_wall) & 3620 * surf_usm_h%wghf_eb(m) + & 3621 surf_usm_h%frac(m,ind_pav_green) & 3622 * surf_usm_h%wghf_eb_green(m) + & 3623 surf_usm_h%frac(m,ind_wat_win) & 3624 * surf_usm_h%wghf_eb_window(m) 3625 ENDDO 3626 DO l = 0, 3 3627 DO m = 1, surf_usm_v(l)%ns 3628 surf_usm_v(l)%ghf(m) = surf_usm_v(l)%frac(m,ind_veg_wall) & 3629 * surf_usm_v(l)%wghf_eb(m) + & 3630 surf_usm_v(l)%frac(m,ind_pav_green)& 3631 * surf_usm_v(l)%wghf_eb_green(m) + & 3632 surf_usm_v(l)%frac(m,ind_wat_win) & 3633 * surf_usm_v(l)%wghf_eb_window(m) 3634 ENDDO 3635 ENDDO 3636 3563 3637 CALL surface_data_output_sum_up( surf_def_h(0)%ghf, & 3564 3638 surf_def_h(1)%ghf, & … … 3846 3920 var_def_v1, var_lsm_v1, var_usm_v1, & 3847 3921 var_def_v2, var_lsm_v2, var_usm_v2, & 3848 var_def_v3, var_lsm_v3, var_usm_v3, n_out ) 3922 var_def_v3, var_lsm_v3, var_usm_v3, n_out,& 3923 fac ) 3849 3924 3850 3925 IMPLICIT NONE 3851 3926 3927 INTEGER(iwp) :: k !< height index of surface element 3852 3928 INTEGER(iwp) :: m !< running index for surface elements 3853 3929 INTEGER(iwp) :: n_out !< index for output variable 3854 3930 INTEGER(iwp) :: n_surf !< running index for surface elements 3931 3932 REAL(wp), DIMENSION(:), OPTIONAL :: fac !< passed output conversion factor for heatflux output 3933 REAL(wp), DIMENSION(nzb:nzt+1) :: conversion_factor !< effective array for output conversion factor 3855 3934 3856 3935 REAL(wp), DIMENSION(:), ALLOCATABLE, INTENT(IN) :: var_def_h0 !< output variable at upward-facing default-type surfaces … … 3872 3951 3873 3952 ! 3953 !-- Set conversion factor to one if not present 3954 IF ( .NOT. PRESENT( fac ) ) THEN 3955 conversion_factor = 1.0_wp 3956 ELSE 3957 conversion_factor = fac 3958 ENDIF 3959 ! 3874 3960 !-- Set counter variable to zero before the variable is written to 3875 3961 !-- the output array. … … 3888 3974 DO m = 1, surf_def_h(0)%ns 3889 3975 n_surf = n_surf + 1 3976 k = surf_def_h(0)%k(m) 3890 3977 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3891 + var_def_h0(m) 3978 + var_def_h0(m) * conversion_factor(k) 3892 3979 ENDDO 3893 3980 ELSE … … 3897 3984 DO m = 1, surf_def_h(1)%ns 3898 3985 n_surf = n_surf + 1 3986 k = surf_def_h(1)%k(m) 3899 3987 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3900 + var_def_h1(m) 3988 + var_def_h1(m) * conversion_factor(k) 3901 3989 ENDDO 3902 3990 ELSE … … 3906 3994 DO m = 1, surf_lsm_h%ns 3907 3995 n_surf = n_surf + 1 3996 k = surf_lsm_h%k(m) 3908 3997 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3909 + var_lsm_h(m) 3998 + var_lsm_h(m) * conversion_factor(k) 3910 3999 ENDDO 3911 4000 ELSE … … 3915 4004 DO m = 1, surf_usm_h%ns 3916 4005 n_surf = n_surf + 1 4006 k = surf_usm_h%k(m) 3917 4007 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3918 + var_usm_h(m) 4008 + var_usm_h(m) * conversion_factor(k) 3919 4009 ENDDO 3920 4010 ELSE … … 3926 4016 DO m = 1, surf_def_v(0)%ns 3927 4017 n_surf = n_surf + 1 4018 k = surf_def_v(0)%k(m) 3928 4019 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3929 + var_def_v0(m) 4020 + var_def_v0(m) * conversion_factor(k) 3930 4021 ENDDO 3931 4022 ELSE … … 3935 4026 DO m = 1, surf_lsm_v(0)%ns 3936 4027 n_surf = n_surf + 1 4028 k = surf_lsm_v(0)%k(m) 3937 4029 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3938 + var_lsm_v0(m) 4030 + var_lsm_v0(m) * conversion_factor(k) 3939 4031 ENDDO 3940 4032 ELSE … … 3944 4036 DO m = 1, surf_usm_v(0)%ns 3945 4037 n_surf = n_surf + 1 4038 k = surf_usm_v(0)%k(m) 3946 4039 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3947 + var_usm_v0(m) 4040 + var_usm_v0(m) * conversion_factor(k) 3948 4041 ENDDO 3949 4042 ELSE … … 3955 4048 DO m = 1, surf_def_v(1)%ns 3956 4049 n_surf = n_surf + 1 4050 k = surf_def_v(1)%k(m) 3957 4051 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3958 + var_def_v1(m) 4052 + var_def_v1(m) * conversion_factor(k) 3959 4053 ENDDO 3960 4054 ELSE … … 3964 4058 DO m = 1, surf_lsm_v(1)%ns 3965 4059 n_surf = n_surf + 1 4060 k = surf_lsm_v(1)%k(m) 3966 4061 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3967 + var_lsm_v1(m) 4062 + var_lsm_v1(m) * conversion_factor(k) 3968 4063 ENDDO 3969 4064 ELSE … … 3973 4068 DO m = 1, surf_usm_v(1)%ns 3974 4069 n_surf = n_surf + 1 4070 k = surf_usm_v(1)%k(m) 3975 4071 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3976 + var_usm_v1(m) 4072 + var_usm_v1(m) * conversion_factor(k) 3977 4073 ENDDO 3978 4074 ELSE … … 3984 4080 DO m = 1, surf_def_v(2)%ns 3985 4081 n_surf = n_surf + 1 4082 k = surf_def_v(2)%k(m) 3986 4083 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3987 + var_def_v2(m) 4084 + var_def_v2(m) * conversion_factor(k) 3988 4085 ENDDO 3989 4086 ELSE … … 3993 4090 DO m = 1, surf_lsm_v(2)%ns 3994 4091 n_surf = n_surf + 1 4092 k = surf_lsm_v(2)%k(m) 3995 4093 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 3996 + var_lsm_v2(m) 4094 + var_lsm_v2(m) * conversion_factor(k) 3997 4095 ENDDO 3998 4096 ELSE … … 4002 4100 DO m = 1, surf_usm_v(2)%ns 4003 4101 n_surf = n_surf + 1 4102 k = surf_usm_v(2)%k(m) 4004 4103 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 4005 + var_usm_v2(m) 4104 + var_usm_v2(m) * conversion_factor(k) 4006 4105 ENDDO 4007 4106 ELSE … … 4013 4112 DO m = 1, surf_def_v(3)%ns 4014 4113 n_surf = n_surf + 1 4114 k = surf_def_v(3)%k(m) 4015 4115 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 4016 + var_def_v3(m) 4116 + var_def_v3(m) * conversion_factor(k) 4017 4117 ENDDO 4018 4118 ELSE … … 4022 4122 DO m = 1, surf_lsm_v(3)%ns 4023 4123 n_surf = n_surf + 1 4124 k = surf_lsm_v(3)%k(m) 4024 4125 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 4025 + var_lsm_v3(m) 4126 + var_lsm_v3(m) * conversion_factor(k) 4026 4127 ENDDO 4027 4128 ELSE … … 4031 4132 DO m = 1, surf_usm_v(3)%ns 4032 4133 n_surf = n_surf + 1 4134 k = surf_usm_v(3)%k(m) 4033 4135 surfaces%var_av(n_surf,n_out) = surfaces%var_av(n_surf,n_out) & 4034 + var_usm_v3(m) 4136 + var_usm_v3(m) * conversion_factor(k) 4035 4137 ENDDO 4036 4138 ELSE … … 4050 4152 var_def_v1, var_lsm_v1, var_usm_v1, & 4051 4153 var_def_v2, var_lsm_v2, var_usm_v2, & 4052 var_def_v3, var_lsm_v3, var_usm_v3 ) 4154 var_def_v3, var_lsm_v3, var_usm_v3, & 4155 fac ) 4053 4156 4054 4157 IMPLICIT NONE 4055 4158 4159 INTEGER(iwp) :: k !< height index of surface element 4056 4160 INTEGER(iwp) :: m !< running index for surface elements 4057 4161 INTEGER(iwp) :: n_surf !< running index for surface elements 4162 4163 REAL(wp), DIMENSION(:), OPTIONAL :: fac !< passed output conversion factor for heatflux output 4164 REAL(wp), DIMENSION(nzb:nzt+1) :: conversion_factor !< effective array for output conversion factor 4058 4165 4059 4166 REAL(wp), DIMENSION(:), ALLOCATABLE, INTENT(IN) :: var_def_h0 !< output variable at upward-facing default-type surfaces … … 4075 4182 4076 4183 ! 4184 !-- Set conversion factor to one if not present 4185 IF ( .NOT. PRESENT( fac ) ) THEN 4186 conversion_factor = 1.0_wp 4187 ELSE 4188 conversion_factor = fac 4189 ENDIF 4190 ! 4077 4191 !-- Set counter variable to zero before the variable is written to 4078 4192 !-- the output array. 4079 4193 n_surf = 0 4080 4081 4194 ! 4082 4195 !-- Write the horizontal surfaces. … … 4085 4198 !-- If a variable is not defined, skip the block and increment the counter 4086 4199 !-- variable by the number of surface elements of this type. Usually this 4087 !-- is zer e, however, there might be the situation that e.g. urban surfaces4200 !-- is zero, however, there might be the situation that e.g. urban surfaces 4088 4201 !-- are defined but the respective variable is not allocated for this surface 4089 4202 !-- type. To write the data on the exact position, increment the counter. … … 4091 4204 DO m = 1, surf_def_h(0)%ns 4092 4205 n_surf = n_surf + 1 4093 surfaces%var_out(n_surf) = var_def_h0(m) 4206 k = surf_def_h(0)%k(m) 4207 surfaces%var_out(n_surf) = var_def_h0(m) * conversion_factor(k) 4094 4208 ENDDO 4095 4209 ELSE … … 4099 4213 DO m = 1, surf_def_h(1)%ns 4100 4214 n_surf = n_surf + 1 4101 surfaces%var_out(n_surf) = var_def_h1(m) 4215 k = surf_def_h(1)%k(m) 4216 surfaces%var_out(n_surf) = var_def_h1(m) * conversion_factor(k) 4102 4217 ENDDO 4103 4218 ELSE … … 4107 4222 DO m = 1, surf_lsm_h%ns 4108 4223 n_surf = n_surf + 1 4109 surfaces%var_out(n_surf) = var_lsm_h(m) 4224 k = surf_lsm_h%k(m) 4225 surfaces%var_out(n_surf) = var_lsm_h(m) * conversion_factor(k) 4110 4226 ENDDO 4111 4227 ELSE … … 4115 4231 DO m = 1, surf_usm_h%ns 4116 4232 n_surf = n_surf + 1 4117 surfaces%var_out(n_surf) = var_usm_h(m) 4233 k = surf_usm_h%k(m) 4234 surfaces%var_out(n_surf) = var_usm_h(m) * conversion_factor(k) 4118 4235 ENDDO 4119 4236 ELSE … … 4125 4242 DO m = 1, surf_def_v(0)%ns 4126 4243 n_surf = n_surf + 1 4127 surfaces%var_out(n_surf) = var_def_v0(m) 4244 k = surf_def_v(0)%k(m) 4245 surfaces%var_out(n_surf) = var_def_v0(m) * conversion_factor(k) 4128 4246 ENDDO 4129 4247 ELSE … … 4133 4251 DO m = 1, surf_lsm_v(0)%ns 4134 4252 n_surf = n_surf + 1 4135 surfaces%var_out(n_surf) = var_lsm_v0(m) 4253 k = surf_lsm_v(0)%k(m) 4254 surfaces%var_out(n_surf) = var_lsm_v0(m) * conversion_factor(k) 4136 4255 ENDDO 4137 4256 ELSE … … 4141 4260 DO m = 1, surf_usm_v(0)%ns 4142 4261 n_surf = n_surf + 1 4143 surfaces%var_out(n_surf) = var_usm_v0(m) 4262 k = surf_usm_v(0)%k(m) 4263 surfaces%var_out(n_surf) = var_usm_v0(m) * conversion_factor(k) 4144 4264 ENDDO 4145 4265 ELSE … … 4151 4271 DO m = 1, surf_def_v(1)%ns 4152 4272 n_surf = n_surf + 1 4153 surfaces%var_out(n_surf) = var_def_v1(m) 4273 k = surf_def_v(1)%k(m) 4274 surfaces%var_out(n_surf) = var_def_v1(m) * conversion_factor(k) 4154 4275 ENDDO 4155 4276 ELSE … … 4159 4280 DO m = 1, surf_lsm_v(1)%ns 4160 4281 n_surf = n_surf + 1 4161 surfaces%var_out(n_surf) = var_lsm_v1(m) 4282 k = surf_lsm_v(1)%k(m) 4283 surfaces%var_out(n_surf) = var_lsm_v1(m) * conversion_factor(k) 4162 4284 ENDDO 4163 4285 ELSE … … 4167 4289 DO m = 1, surf_usm_v(1)%ns 4168 4290 n_surf = n_surf + 1 4169 surfaces%var_out(n_surf) = var_usm_v1(m) 4291 k = surf_usm_v(1)%k(m) 4292 surfaces%var_out(n_surf) = var_usm_v1(m) * conversion_factor(k) 4170 4293 ENDDO 4171 4294 ELSE … … 4177 4300 DO m = 1, surf_def_v(2)%ns 4178 4301 n_surf = n_surf + 1 4179 surfaces%var_out(n_surf) = var_def_v2(m) 4302 k = surf_def_v(2)%k(m) 4303 surfaces%var_out(n_surf) = var_def_v2(m) * conversion_factor(k) 4180 4304 ENDDO 4181 4305 ELSE … … 4185 4309 DO m = 1, surf_lsm_v(2)%ns 4186 4310 n_surf = n_surf + 1 4187 surfaces%var_out(n_surf) = var_lsm_v2(m) 4311 k = surf_lsm_v(2)%k(m) 4312 surfaces%var_out(n_surf) = var_lsm_v2(m) * conversion_factor(k) 4188 4313 ENDDO 4189 4314 ELSE … … 4193 4318 DO m = 1, surf_usm_v(2)%ns 4194 4319 n_surf = n_surf + 1 4195 surfaces%var_out(n_surf) = var_usm_v2(m) 4320 k = surf_usm_v(2)%k(m) 4321 surfaces%var_out(n_surf) = var_usm_v2(m) * conversion_factor(k) 4196 4322 ENDDO 4197 4323 ELSE … … 4203 4329 DO m = 1, surf_def_v(3)%ns 4204 4330 n_surf = n_surf + 1 4205 surfaces%var_out(n_surf) = var_def_v3(m) 4331 k = surf_def_v(3)%k(m) 4332 surfaces%var_out(n_surf) = var_def_v3(m) * conversion_factor(k) 4206 4333 ENDDO 4207 4334 ELSE … … 4211 4338 DO m = 1, surf_lsm_v(3)%ns 4212 4339 n_surf = n_surf + 1 4213 surfaces%var_out(n_surf) = var_lsm_v3(m) 4340 k = surf_lsm_v(3)%k(m) 4341 surfaces%var_out(n_surf) = var_lsm_v3(m) * conversion_factor(k) 4214 4342 ENDDO 4215 4343 ELSE … … 4219 4347 DO m = 1, surf_usm_v(3)%ns 4220 4348 n_surf = n_surf + 1 4221 surfaces%var_out(n_surf) = var_usm_v3(m) 4349 k = surf_usm_v(3)%k(m) 4350 surfaces%var_out(n_surf) = var_usm_v3(m) * conversion_factor(k) 4222 4351 ENDDO 4223 4352 ELSE
Note: See TracChangeset
for help on using the changeset viewer.