Skip to content

Commit 0ec8a5f

Browse files
committed
Initial implementation of the scaled coxmunk BRDF.
1 parent 891cc2c commit 0ec8a5f

39 files changed

+1303
-74
lines changed

Makefile.in

Lines changed: 78 additions & 24 deletions
Large diffs are not rendered by default.

input/common/config/config_common.lua

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2297,6 +2297,59 @@ function ConfigCommon.lambertian_retrieval:initial_guess()
22972297
return ig
22982298
end
22992299

2300+
------------------------------------------------------------
2301+
--- Lambertian ground state vector component and initial guess
2302+
------------------------------------------------------------
2303+
2304+
ConfigCommon.brdf_scale_retrieval = CreatorMultiSpec:new {}
2305+
2306+
function ConfigCommon.brdf_scale_retrieval:create()
2307+
local num_coeff = self:apriori_v(0):rows()
2308+
local num_spec = self.config.number_pixel:rows()
2309+
2310+
local ap = Blitz_double_array_2d(num_spec, num_coeff)
2311+
local flag = Blitz_bool_array_2d(num_spec, num_coeff)
2312+
2313+
for i = 1, num_spec do
2314+
ap:set(i-1, Range.all(), self:apriori_v(i - 1))
2315+
flag:set(i-1, Range.all(), self:retrieval_flag(i))
2316+
end
2317+
2318+
local lambertian = GroundBrdfWeight(ap, flag,
2319+
self.config.common.band_reference,
2320+
self.config.common.desc_band_name,
2321+
self.scaled_brdf_name)
2322+
return lambertian
2323+
end
2324+
2325+
function ConfigCommon.brdf_scale_retrieval:initial_guess()
2326+
local ig = CompositeInitialGuess()
2327+
for i=1,self.config.number_pixel:rows() do
2328+
local flag = self:retrieval_flag(i)
2329+
2330+
local ap = self:apriori_v(i - 1)
2331+
local apcov_in = self:covariance_v(i - 1)
2332+
2333+
-- Copy input covariance to modified one which repeats the last covariance value if
2334+
-- the number of degrees is defined
2335+
local apcov_mod = Blitz_double_array_2d(ap:rows(), ap:rows())
2336+
apcov_mod:set(Range.all(), Range.all(), 0.0)
2337+
src_idx = 0
2338+
for dst_idx = 0, ap:rows()-1 do
2339+
apcov_mod:set(dst_idx, dst_idx, apcov_in(src_idx, src_idx))
2340+
if dst_idx < apcov_in:rows()-1 then
2341+
src_idx = src_idx + 1
2342+
end
2343+
end
2344+
2345+
local band_ig = InitialGuessValue()
2346+
band_ig:apriori_subset(flag, ap)
2347+
band_ig:apriori_covariance_subset(flag, apcov_mod)
2348+
ig:add_builder(band_ig)
2349+
end
2350+
return ig
2351+
end
2352+
23002353
------------------------------------------------------------
23012354
--- Creates a GroundOco only using a Lambertian retrieval
23022355
------------------------------------------------------------
@@ -2345,7 +2398,7 @@ function ConfigCommon.ground_coxmunk:register_output(ro)
23452398
end
23462399

23472400
------------------------------------------------------------
2348-
--- Creates a GroundOco using both Lambertioan and Coxmunk
2401+
--- Creates a GroundOco using both Lambertian and Coxmunk
23492402
--- retrieval
23502403
------------------------------------------------------------
23512404

@@ -2364,6 +2417,26 @@ function ConfigCommon.ground_coxmunk_plus_lamb:register_output(ro)
23642417
ro:push_back(GroundCoxmunkPlusLambertianOutput.create(self.config.coxmunk, self.config.coxmunk_lambertian, self.config.common.hdf_band_name))
23652418
end
23662419

2420+
------------------------------------------------------------
2421+
--- Creates a GroundOco using both Lambertian and Coxmunk
2422+
--- retrieval
2423+
------------------------------------------------------------
2424+
2425+
ConfigCommon.ground_coxmunk_scaled = CompositeCreator:new {}
2426+
2427+
function ConfigCommon.ground_coxmunk_scaled:sub_object_key()
2428+
-- Ordering is important here or else the statevector is setup incorrectly
2429+
return { "coxmunk", "coxmunk_scaled" }
2430+
end
2431+
2432+
function ConfigCommon.ground_coxmunk_scaled:create_parent_object(sub_object)
2433+
return GroundCoxmunkScaled.create(self.config.coxmunk, self.config.coxmunk_scaled)
2434+
end
2435+
2436+
function ConfigCommon.ground_coxmunk_scaled:register_output(ro)
2437+
ro:push_back(GroundCoxmunkScaledOutput.create(self.config.l1b, self.config.coxmunk, self.config.coxmunk_scaled, self.config.common.hdf_band_name))
2438+
end
2439+
23672440
------------------------------------------------------------
23682441
--- Modify the GroundBrdf a_priori, scaling by the
23692442
--- kernel value

input/geocarb/config/geocarb_base_config.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,15 @@ GeocarbBaseConfig = GeocarbConfig:new {
471471
creator = ConfigCommon.lambertian_retrieval,
472472
},
473473

474+
-- Lambertian component of coxmunk + lambertian
475+
coxmunk_scaled = {
476+
apriori = ConfigCommon.hdf_apriori_i("Ground/Coxmunk_Scaled"),
477+
covariance = ConfigCommon.hdf_covariance_i("Ground/Coxmunk_Scaled"),
478+
retrieve_bands = { true, true, true, true },
479+
scaled_brdf_name = "CoxMunk",
480+
creator = ConfigCommon.brdf_scale_retrieval,
481+
},
482+
474483
-- Brdf vegetative kernel with Rahman retrieved parameters
475484
brdf_veg = {
476485
apriori = ConfigCommon.brdf_veg_apriori("Ground/Brdf"),

input/geocarb/config/geocarb_config.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,28 @@ function GeocarbConfig.ground_from_ground_type:get_creator()
357357
end
358358
end
359359

360+
GeocarbConfig.ground_from_ground_type_scaled = DispatchCreator:new()
361+
362+
function GeocarbConfig.ground_from_ground_type_scaled:get_creator()
363+
local ground_type = self.config:ground_type_name()
364+
365+
if (ground_type == "lambertian") then
366+
return ConfigCommon.ground_lambertian
367+
elseif (ground_type == "brdf_soil") then
368+
return ConfigCommon.ground_brdf_soil
369+
elseif (ground_type == "brdf_veg") then
370+
return ConfigCommon.ground_brdf_veg
371+
elseif (ground_type == "coxmunk") then
372+
if(self.config.using_radiance_scaling ~= nil) then
373+
return ConfigCommon.ground_coxmunk
374+
else
375+
return ConfigCommon.ground_coxmunk_scaled
376+
end
377+
else
378+
error("Invalid ground type value: " .. ground_type)
379+
end
380+
end
381+
360382
------------------------------------------------------------
361383
--- Create lambertian ground initial guess from radiance
362384
--- but the other parts from the static HDF file
5.44 KB
Binary file not shown.

input/oco/config/oco_base_config.lua

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,15 @@ OcoBaseConfig = OcoConfig:new {
466466
creator = ConfigCommon.lambertian_retrieval,
467467
},
468468

469+
-- Lambertian component of coxmunk + lambertian
470+
coxmunk_scaled = {
471+
apriori = ConfigCommon.hdf_apriori_i("Ground/Coxmunk_Scaled"),
472+
covariance = ConfigCommon.hdf_covariance_i("Ground/Coxmunk_Scaled"),
473+
retrieve_bands = { true, true, true },
474+
scaled_brdf_name = "CoxMunk",
475+
creator = ConfigCommon.brdf_scale_retrieval,
476+
},
477+
469478
-- Brdf vegetative kernel with Rahman retrieved parameters
470479
brdf_veg = {
471480
apriori = ConfigCommon.brdf_veg_apriori("Ground/BrdfQuadratic"),
@@ -526,7 +535,8 @@ OcoBaseConfig = OcoConfig:new {
526535
creator = ConfigCommon.absorber_creator,
527536
gases = {"CO2", "H2O", "O2"},
528537
CO2 = {
529-
apriori = ConfigCommon.co2_profile_file_apriori,
538+
apriori = ConfigCommon.reference_co2_apriori_met_apriori,
539+
-- apriori = ConfigCommon.co2_profile_file_apriori,
530540
covariance = ConfigCommon.hdf_covariance("Gas/CO2"),
531541
absco = "v5.0_alpha/raw/co2_devi2015_wco2scale=nist_sco2scale=unity.hdf",
532542
table_scale = {1.0, 1.0, 1.004},

input/oco/config/oco_config.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,28 @@ function OcoConfig.ground_from_ground_type:get_creator()
374374
end
375375
end
376376

377+
OcoConfig.ground_from_ground_type_scaled = DispatchCreator:new()
378+
379+
function OcoConfig.ground_from_ground_type_scaled:get_creator()
380+
local ground_type = self.config:ground_type_name()
381+
382+
if (ground_type == "lambertian") then
383+
return ConfigCommon.ground_lambertian
384+
elseif (ground_type == "brdf_soil") then
385+
return ConfigCommon.ground_brdf_soil
386+
elseif (ground_type == "brdf_veg") then
387+
return ConfigCommon.ground_brdf_veg
388+
elseif (ground_type == "coxmunk") then
389+
if(self.config.using_radiance_scaling ~= nil) then
390+
return ConfigCommon.ground_coxmunk
391+
else
392+
return ConfigCommon.ground_coxmunk_scaled
393+
end
394+
else
395+
error("Invalid ground type value: " .. ground_type)
396+
end
397+
end
398+
377399
------------------------------------------------------------
378400
--- Create lambertian ground initial guess from radiance
379401
--- but the other parts from the static HDF file
5.7 KB
Binary file not shown.
5.7 KB
Binary file not shown.

lib/Implementation/brdf_functions.F90

Lines changed: 175 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module brdf_functions_m
44

55
USE LIDORT_pars, only : fpk, DEG_TO_RAD, MAXBEAMS, MAXSTREAMS_BRDF, MAX_BRDF_KERNELS, &
66
MAXSTHALF_BRDF, MAX_BRDF_PARAMETERS, ZERO, ONE, TWO, PIE, &
7-
MAX_USER_STREAMS, MAX_USER_RELAZMS, &
7+
MAX_USER_STREAMS, MAX_USER_RELAZMS, COXMUNK_IDX, &
88
BREONVEG_IDX, BREONSOIL_IDX, RAHMAN_IDX
99

1010
implicit none
@@ -28,7 +28,18 @@ real(kind=c_double) function exact_brdf_value_soil_f(params, sza, vza, azm) bind
2828

2929
exact_brdf_value_soil_f = exact_brdf_value_f(BREONSOIL_IDX, params, sza, vza, azm)
3030
end function exact_brdf_value_soil_f
31-
31+
32+
real(kind=c_double) function exact_brdf_value_coxmunk(params, sza, vza, azm) bind(c)
33+
real(kind=c_double), intent(in) :: params(5)
34+
real(kind=c_double), intent(in) :: sza
35+
real(kind=c_double), intent(in) :: vza
36+
real(kind=c_double), intent(in) :: azm
37+
38+
exact_brdf_value_coxmunk = exact_brdf_value_cm_f(params, sza, vza, azm)
39+
end function exact_brdf_value_coxmunk
40+
41+
!------------------------------------------------------------------------------
42+
3243
real(kind=c_double) function exact_brdf_value_f(breon_type, params, sza, vza, azm) bind(c)
3344

3445
USE brdf_sup_routines_m, only : BRDF_FUNCTION
@@ -200,6 +211,168 @@ real(kind=c_double) function exact_brdf_value_f(breon_type, params, sza, vza, az
200211

201212
END FUNCTION exact_brdf_value_f
202213

214+
!------------------------------------------------------------------------------
215+
216+
real(kind=c_double) function exact_brdf_value_cm_f(params, sza, vza, azm) bind(c)
217+
218+
USE brdf_sup_routines_m, only : BRDF_FUNCTION
219+
220+
! Parameters for lrad
221+
222+
INTEGER, PARAMETER :: NSTOKES = 3
223+
INTEGER, PARAMETER :: NSPARS = 5
224+
225+
real(kind=c_double), intent(in) :: params(NSPARS)
226+
real(kind=c_double), intent(in) :: sza
227+
real(kind=c_double), intent(in) :: vza
228+
real(kind=c_double), intent(in) :: azm
229+
230+
! Number and index-list of bidirectional functions
231+
232+
INTEGER :: N_BRDF_KERNELS
233+
INTEGER :: WHICH_BRDF ( MAX_BRDF_KERNELS )
234+
235+
! Parameters required for Kernel families
236+
237+
INTEGER :: N_BRDF_PARAMETERS ( MAX_BRDF_KERNELS )
238+
REAL(fpk) :: BRDF_PARAMETERS ( MAX_BRDF_KERNELS, MAX_BRDF_PARAMETERS )
239+
240+
! Input kernel amplitude factors
241+
242+
REAL(fpk) :: BRDF_FACTORS ( MAX_BRDF_KERNELS )
243+
244+
! Cos and since of SZAs
245+
246+
REAL(fpk) :: SZASURCOS(MAXBEAMS)
247+
REAL(fpk) :: SZASURSIN(MAXBEAMS)
248+
249+
! Local angle control
250+
251+
INTEGER :: NBEAMS
252+
INTEGER :: N_USER_STREAMS
253+
INTEGER :: N_USER_RELAZMS
254+
255+
! Angles
256+
257+
REAL(fpk) :: BEAM_SZAS (MAXBEAMS)
258+
REAL(fpk) :: USER_ANGLES_INPUT (MAX_USER_STREAMS)
259+
REAL(fpk) :: USER_RELAZMS (MAX_USER_RELAZMS)
260+
REAL(fpk) :: USER_STREAMS (MAX_USER_STREAMS)
261+
REAL(fpk) :: USER_SINES (MAX_USER_STREAMS)
262+
REAL(fpk) :: PHIANG (MAX_USER_RELAZMS)
263+
REAL(fpk) :: COSPHI (MAX_USER_RELAZMS)
264+
REAL(fpk) :: SINPHI (MAX_USER_RELAZMS)
265+
266+
! Exact DB values from LIDORT
267+
268+
REAL(fpk) :: EXACTDB_BRDFUNC ( MAX_USER_STREAMS, MAX_USER_RELAZMS, MAXBEAMS )
269+
270+
! Lrad variables
271+
272+
INTEGER :: HFUNCTION_INDEX
273+
real(fpk) :: SPARS(NSPARS)
274+
real(fpk) :: XI, SXI, XJ, SXJ
275+
real(fpk) :: CKPHI_REF, SKPHI_REF
276+
real(fpk) :: R1(NSTOKES)
277+
278+
! Calculated BRDF
279+
280+
REAL(fpk) :: EXACT_CALC_BRDF
281+
282+
! Help
283+
284+
INTEGER :: IB, K, UI, IA
285+
REAL(fpk) :: MUX
286+
287+
! Set values for the basic LIDORT variables
288+
289+
N_BRDF_KERNELS = 1
290+
WHICH_BRDF(1) = COXMUNK_IDX
291+
N_BRDF_PARAMETERS(1) = 2
292+
BRDF_PARAMETERS = ZERO
293+
! Breon refactive index squared, same as value hardcoded inside lrad
294+
BRDF_PARAMETERS(1,1) = params(1)
295+
BRDF_PARAMETERS(1,2) = params(2)
296+
BRDF_FACTORS(1) = 1.
297+
NBEAMS = 1
298+
BEAM_SZAS(1) = sza
299+
N_USER_STREAMS = 1
300+
USER_ANGLES_INPUT(1) = vza
301+
N_USER_RELAZMS = 1
302+
USER_RELAZMS(1) = azm
303+
304+
! Set values for the basic l_rad variables
305+
306+
spars(1) = 1.
307+
spars(2) = BRDF_PARAMETERS(1,1)
308+
spars(3) = BRDF_PARAMETERS(1,2)
309+
spars(4) = 0.
310+
spars(5) = 0.
311+
312+
! Cosine and since of SZA
313+
314+
DO IB = 1, NBEAMS
315+
MUX = COS(BEAM_SZAS(IB)*DEG_TO_RAD)
316+
SZASURCOS(IB) = MUX
317+
SZASURSIN(IB) = SQRT(1.0_fpk-MUX*MUX)
318+
ENDDO
319+
320+
XI = SZASURCOS(1)
321+
SXI = SZASURSIN(1)
322+
323+
! Cosine and since of VZA
324+
325+
DO UI = 1, N_USER_STREAMS
326+
MUX = COS(USER_ANGLES_INPUT(UI)*DEG_TO_RAD)
327+
USER_STREAMS(UI) = MUX
328+
USER_SINES(UI) = SQRT(1.0_fpk-MUX*MUX)
329+
ENDDO
330+
331+
XJ = USER_STREAMS(1)
332+
SXJ = USER_SINES(1)
333+
334+
! Cosine and since of AZM
335+
336+
DO IA = 1, N_USER_RELAZMS
337+
PHIANG(IA) = USER_RELAZMS(IA)*DEG_TO_RAD
338+
COSPHI(IA) = COS(PHIANG(IA))
339+
SINPHI(IA) = SIN(PHIANG(IA))
340+
ENDDO
341+
342+
CKPHI_REF = COSPHI(1)
343+
SKPHI_REF = SINPHI(1)
344+
345+
! Exact BRDF (LIDORT)
346+
! -------------------
347+
348+
EXACT_CALC_BRDF = ZERO
349+
350+
! Kernel loop
351+
352+
DO K = 1, N_BRDF_KERNELS
353+
354+
DO IA = 1, N_USER_RELAZMS
355+
DO IB = 1, NBEAMS
356+
DO UI = 1, N_USER_STREAMS
357+
CALL BRDF_FUNCTION &
358+
( MAX_BRDF_PARAMETERS, WHICH_BRDF(K), N_BRDF_PARAMETERS(K), BRDF_PARAMETERS(K,:), & ! Inputs
359+
SZASURCOS(IB), SZASURSIN(IB), USER_STREAMS(UI), & ! Inputs
360+
USER_SINES(UI), PHIANG(IA), COSPHI(IA), SINPHI(IA), & ! Inputs
361+
EXACTDB_BRDFUNC(UI,IA,IB) ) ! Output
362+
ENDDO
363+
ENDDO
364+
ENDDO
365+
366+
EXACT_CALC_BRDF = EXACT_CALC_BRDF + BRDF_FACTORS(K) * EXACTDB_BRDFUNC(1,1,1)
367+
368+
ENDDO
369+
370+
exact_brdf_value_cm_f = EXACT_CALC_BRDF
371+
372+
END FUNCTION exact_brdf_value_cm_f
373+
374+
!------------------------------------------------------------------------------
375+
203376
real(kind=c_double) function black_sky_albedo_veg_f(params, sza) bind(c)
204377
real(kind=c_double), intent(in) :: params(5)
205378
real(kind=c_double), intent(in) :: sza

0 commit comments

Comments
 (0)