10 use ai_aerosol,
only : aerosol_t
11 use ai_aerosol_state,
only : aerosol_state_t
14 use musica_constants,
only : musica_dk
25 real(kind=musica_dk) :: geometric_mean_diameter__m_
27 real(kind=musica_dk) :: geometric_standard_deviation_
69 real(kind=musica_dk) :: wet_number_mode_diameter__m_
72 real(kind=musica_dk) :: number_mixing_ratio__num_mol_
74 real(kind=musica_dk),
allocatable :: mass_mixing_ratio__kg_kg_(:)
89 use musica_config,
only : config_t
90 use musica_iterator,
only : iterator_t
93 class(config_t),
intent(inout) :: config
95 character(len=*),
parameter :: my_name =
"MAM mode_t constructor"
96 type(config_t) :: optics_config, species_set, species
97 class(iterator_t),
pointer :: iter
100 call config%get(
"geometric mean diameter of number distribution",
"m", &
101 new_obj%geometric_mean_diameter__m_, my_name )
102 call config%get(
"geometric standard deviation of number distribution", &
103 new_obj%geometric_standard_deviation_, my_name )
104 call config%get(
"species", species_set, my_name )
105 allocate( new_obj%species_( species_set%number_of_children( ) ) )
106 iter => species_set%get_iterator( )
108 do while( iter%next( ) )
109 call species_set%get( iter, species, my_name )
110 call species%add(
"name", species_set%key( iter ), my_name )
111 new_obj%species_( i_species ) =
species_t( species )
112 i_species = i_species + 1
114 call config%get(
"shortwave lookup tables", optics_config, my_name )
116 call config%get(
"longwave lookup tables", optics_config, my_name )
127 use ai_aerosol_state,
only : aerosol_state_t
129 class(aerosol_state_t),
pointer ::
new_state
130 class(
mode_t),
intent(in) :: this
135 allocate(
new_state%mass_mixing_ratio__kg_kg_(
size( this%species_ ) ) )
143 function new_optics( this, property, output_grid, interpolation_strategy )
145 use ai_optics,
only : optics_t
146 use ai_wavelength_grid,
only : wavelength_grid_t
148 use musica_interpolator,
only : interpolation_strategy_i
149 use musica_property,
only : property_t
152 class(
mode_t),
intent(in) :: this
153 class(property_t),
intent(in) :: property
154 type(wavelength_grid_t),
intent(in) :: output_grid
155 procedure(interpolation_strategy_i),
optional :: interpolation_strategy
159 this%longwave_lookup_%grid( ), output_grid, &
160 interpolation_strategy )
168 aerosol_state, optics )
170 use ai_environmental_state,
only : environmental_state_t
171 use ai_optics,
only : optics_t, optics_ptr
173 class(
mode_t),
intent(in) :: this
174 class(environmental_state_t),
intent(in) :: environmental_state
175 class(aerosol_state_t),
intent(in) :: aerosol_state
176 class(optics_t),
target,
intent(inout) :: optics
178 type(optics_ptr) :: optics_set(1)
180 optics_set(1)%ptr_ => optics
181 call this%shortwave_optics( environmental_state, aerosol_state, &
183 nullify( optics_set(1)%ptr_ )
191 aerosol_state, optics )
193 use ai_environmental_state,
only : environmental_state_t
194 use ai_optics,
only : optics_ptr
195 use musica_assert,
only : die_msg
197 class(
mode_t),
intent(in) :: this
198 class(environmental_state_t),
intent(in) :: environmental_state
199 class(aerosol_state_t),
intent(in) :: aerosol_state
200 type(optics_ptr),
intent(inout) :: optics(:)
204 select type( aerosol_state )
206 do i_prop = 1,
size( optics )
207 call optics( i_prop )%ptr_%reset_values( )
209 call this%add_shortwave_optics( environmental_state, aerosol_state, &
212 call die_msg( 713383720,
"Invalid state passed to MAM mode shortwave "//&
213 "optics calculator" )
222 aerosol_state, optics )
224 use ai_environmental_state,
only : environmental_state_t
225 use ai_optics,
only : optics_t, optics_ptr
227 class(
mode_t),
intent(in) :: this
228 class(environmental_state_t),
intent(in) :: environmental_state
229 class(aerosol_state_t),
intent(in) :: aerosol_state
230 class(optics_t),
target,
intent(inout) :: optics
232 type(optics_ptr) :: optics_set(1)
234 optics_set(1)%ptr_ => optics
235 call this%longwave_optics( environmental_state, aerosol_state, &
237 nullify( optics_set(1)%ptr_ )
245 aerosol_state, optics )
247 use ai_environmental_state,
only : environmental_state_t
248 use ai_optics,
only : optics_ptr
249 use musica_assert,
only : die_msg
251 class(
mode_t),
intent(in) :: this
252 class(environmental_state_t),
intent(in) :: environmental_state
253 class(aerosol_state_t),
intent(in) :: aerosol_state
254 type(optics_ptr),
intent(inout) :: optics(:)
258 select type( aerosol_state )
260 do i_prop = 1,
size( optics )
261 call optics( i_prop )%ptr_%reset_values( )
263 call this%add_longwave_optics( environmental_state, aerosol_state, &
266 call die_msg( 713383720,
"Invalid state passed to MAM mode longwave "// &
267 "optics calculator" )
277 use ai_wavelength_grid,
only : wavelength_grid_t
280 class(
mode_t),
intent(in) :: this
291 use ai_wavelength_grid,
only : wavelength_grid_t
294 class(
mode_t),
intent(in) :: this
305 use musica_assert,
only : die_msg
306 use musica_string,
only : to_char
309 class(
mode_t),
intent(in) :: this
311 class(aerosol_state_t),
intent(in) :: aerosol_state
313 integer,
optional,
intent(in) :: io_unit
315 integer :: lunit, i_species
318 if(
present( io_unit ) ) lunit = io_unit
319 select type( aerosol_state )
321 write(lunit,*)
"** MAM Mode State **"
322 if( .not.
allocated( this%species_ ) )
then
323 write(lunit,*)
"--- Uninitialized MAM Mode ---"
324 write(lunit,*)
"** End MAM Mode State **"
327 if( .not.
allocated( aerosol_state%mass_mixing_ratio__kg_kg_ ) )
then
328 write(lunit,*)
"--- Uninitialized MAM Mode State ---"
329 write(lunit,*)
"** End MAM Mode State **"
332 write(lunit,*)
"wet mode diameter of number distribution [m]: "// &
334 aerosol_state%wet_number_mode_diameter__m_ ) )
335 write(lunit,*)
"number mixing ratio [# mol]: "//trim( to_char( &
336 aerosol_state%number_mixing_ratio__num_mol_ ) )
337 do i_species = 1,
size( this%species_ )
338 write(lunit,*)
"species '"//this%species_( i_species )%name( )// &
339 "' mass mixing ratio [kg kg-1]: "// &
341 aerosol_state%mass_mixing_ratio__kg_kg_( i_species ) ) )
344 call die_msg( 285756314,
"Invalid state passed to MAM mode" )
356 use ai_environmental_state,
only : environmental_state_t
357 use ai_optics,
only : optics_ptr
360 use musica_math,
only : chebyshev_function
362 class(
mode_t),
intent(in) :: this
363 class(environmental_state_t),
intent(in) :: environmental_state
365 class(optics_ptr),
intent(inout) :: optics(:)
367 integer :: i_prop, n_cheby, n_bands
368 real(kind=musica_dk),
allocatable :: absorption_coefficients(:,:)
369 real(kind=musica_dk),
allocatable :: extinction_coefficients(:,:)
370 real(kind=musica_dk),
allocatable :: asymmetry_factor_coefficients(:,:)
371 real(kind=musica_dk),
allocatable :: size_function(:)
372 complex(kind=musica_dk),
allocatable :: net_refractive_index(:)
373 real(kind=musica_dk),
allocatable ::
absorption(:)
374 real(kind=musica_dk),
allocatable ::
extinction(:)
376 real(kind=musica_dk),
allocatable :: ssa(:)
377 reaL(kind=musica_dk),
allocatable :: layer_aod(:)
378 real(kind=musica_dk) :: normalized_radius
380 n_cheby = this%shortwave_lookup_%number_of_chebyshev_coefficients( )
381 n_bands = this%shortwave_lookup_%number_of_wavelength_bands( )
382 allocate( absorption_coefficients( n_cheby, n_bands ) )
383 allocate( extinction_coefficients( n_cheby, n_bands ) )
384 allocate( asymmetry_factor_coefficients( n_cheby, n_bands ) )
385 allocate( size_function( n_cheby ) )
386 allocate( net_refractive_index( n_bands ) )
390 allocate( ssa( n_bands ) )
391 allocate( layer_aod( n_bands ) )
392 net_refractive_index = &
393 this%net_shortwave_refractive_index( mode_state, n_bands )
395 call this%shortwave_lookup_%get_optics( net_refractive_index, &
400 normalized_radius = this%shortwave_lookup_%normalize_radius( &
401 this%wet_surface_mode_radius__m( mode_state ) )
402 call chebyshev_function( normalized_radius, size_function )
404 extinction = this%specific_extinction__m2_kg( mode_state, n_bands, &
406 extinction_coefficients, &
408 this%shortwave_lookup_ )
409 absorption = this%specific_absorption__m2_kg( mode_state, n_bands, &
411 absorption_coefficients, &
416 asymmetry_factor_coefficients, &
421 layer_aod =
extinction(:) * environmental_state%layer_thickness__Pa( ) &
423 do i_prop = 1,
size( optics )
425 optics( i_prop )%ptr_ )
437 use ai_environmental_state,
only : environmental_state_t
438 use ai_optics,
only : optics_ptr
441 use musica_math,
only : chebyshev_function
443 class(
mode_t),
intent(in) :: this
444 class(environmental_state_t),
intent(in) :: environmental_state
446 class(optics_ptr),
intent(inout) :: optics(:)
448 integer :: i_prop, n_cheby, n_bands
449 real(kind=musica_dk),
allocatable :: absorption_coefficients(:,:)
450 real(kind=musica_dk),
allocatable :: chebyshev_coefficients(:)
451 real(kind=musica_dk),
allocatable :: size_function(:)
452 complex(kind=musica_dk),
allocatable :: net_refractive_index(:)
453 real(kind=musica_dk),
allocatable ::
absorption(:)
454 real(kind=musica_dk),
allocatable :: layer_aod(:)
455 real(kind=musica_dk) :: normalized_radius
457 n_cheby = this%longwave_lookup_%number_of_chebyshev_coefficients( )
458 n_bands = this%longwave_lookup_%number_of_wavelength_bands( )
459 allocate( absorption_coefficients( n_cheby, n_bands ) )
460 allocate( chebyshev_coefficients( n_cheby ) )
461 allocate( size_function( n_cheby ) )
462 allocate( net_refractive_index( n_bands ) )
464 allocate( layer_aod( n_bands ) )
465 net_refractive_index = &
466 this%net_longwave_refractive_index( mode_state, n_bands )
468 call this%longwave_lookup_%get_optics( net_refractive_index, &
471 normalized_radius = this%longwave_lookup_%normalize_radius( &
472 this%wet_surface_mode_radius__m( mode_state ) )
473 call chebyshev_function( normalized_radius, size_function )
475 absorption = this%specific_absorption__m2_kg( mode_state, n_bands, &
477 absorption_coefficients, &
479 layer_aod(:) =
absorption(:) * environmental_state%layer_thickness__Pa( ) &
481 do i_prop = 1,
size( optics )
492 mode_state )
result( gmd )
494 real(kind=musica_dk) :: gmd
495 class(
mode_t),
intent(in) :: this
498 gmd = this%geometric_mean_diameter__m_
507 this, mode_state )
result( gsd )
509 real(kind=musica_dk) :: gsd
510 class(
mode_t),
intent(in) :: this
513 gsd = this%geometric_standard_deviation_
521 mode_state )
result( vmmr )
523 real(kind=musica_dk) :: vmmr
524 class(
mode_t),
intent(in) :: this
530 do i_species = 1,
size( this%species_ )
531 associate( species => this%species_( i_species ), &
533 mode_state%mass_mixing_ratio__kg_kg_( i_species ) )
534 vmmr = vmmr + species%volume__m3( species_mmr )
544 mode_state )
result( radius )
546 class(
mode_t),
intent(in) :: this
549 radius = mode_state%wet_number_mode_diameter__m_ * 0.5_musica_dk
557 mode_state )
result( diameter )
559 class(
mode_t),
intent(in) :: this
562 diameter = mode_state%wet_number_mode_diameter__m_
571 mode_state )
result( radius )
573 class(
mode_t),
intent(in) :: this
576 radius = 2.0_musica_dk * this%wet_surface_mode_radius__m( mode_state )
584 mode_state )
result( radius )
586 class(
mode_t),
intent(in) :: this
589 associate( sigma => &
590 this%geometric_standard_deviation_of_number_distribution( &
592 radius = this%wet_number_mode_radius__m( mode_state ) * &
593 exp( 2.0_musica_dk * ( log( sigma )**2 ) )
603 mode_state )
result( mixing_ratio )
605 class(
mode_t),
intent(in) :: this
608 mixing_ratio = mode_state%number_mixing_ratio__num_mol_
617 number_of_bands )
result( refractive_index )
619 complex(kind=musica_dk) :: refractive_index( number_of_bands )
620 class(
mode_t),
intent(in) :: this
622 integer,
intent(in) :: number_of_bands
624 integer :: i_species,
i_band
625 real(kind=musica_dk) :: total_vmmr, species_vmmr
627 refractive_index(:) = ( 0.0_musica_dk, 0.0_musica_dk )
628 total_vmmr = 0.0_musica_dk
629 do i_species = 1,
size( this%species_ )
630 associate( species => this%species_( i_species ), &
632 mode_state%mass_mixing_ratio__kg_kg_( i_species ) )
633 species_vmmr = species%volume__m3( species_mmr )
634 do i_band = 1, number_of_bands
635 refractive_index(
i_band ) = refractive_index(
i_band ) &
636 + species%shortwave_refractive_index(
i_band ) * species_vmmr
638 total_vmmr = total_vmmr + species_vmmr
641 refractive_index(:) = refractive_index(:) &
642 / max( total_vmmr, 1.0e-60_musica_dk )
651 number_of_bands )
result( refractive_index )
653 complex(kind=musica_dk) :: refractive_index( number_of_bands )
654 class(
mode_t),
intent(in) :: this
656 integer,
intent(in) :: number_of_bands
658 integer :: i_species,
i_band
659 real(kind=musica_dk) :: total_vmmr, species_vmmr
661 refractive_index(:) = ( 0.0_musica_dk, 0.0_musica_dk )
662 total_vmmr = 0.0_musica_dk
663 do i_species = 1,
size( this%species_ )
664 associate( species => this%species_( i_species ), &
666 mode_state%mass_mixing_ratio__kg_kg_( i_species ) )
667 species_vmmr = species%volume__m3( species_mmr )
668 do i_band = 1, number_of_bands
669 refractive_index(
i_band ) = refractive_index(
i_band ) &
670 + species%longwave_refractive_index(
i_band ) * species_vmmr
672 total_vmmr = total_vmmr + species_vmmr
675 refractive_index(:) = refractive_index(:) &
676 / max( total_vmmr, 1.0e-60_musica_dk )
688 number_of_coefficients, coefficients, size_function, max_absorption )
691 use musica_math,
only : weighted_chebyshev
694 class(
mode_t),
intent(in) :: this
696 integer,
intent(in) :: number_of_bands
697 integer,
intent(in) :: number_of_coefficients
699 real(kind=musica_dk),
intent(in) :: coefficients( number_of_coefficients, &
702 real(kind=musica_dk),
intent(in) :: size_function( number_of_coefficients )
704 real(kind=musica_dk),
intent(in),
optional :: max_absorption( &
708 do i_band = 1, number_of_bands
710 absorp = weighted_chebyshev( number_of_coefficients, &
711 coefficients( :,
i_band ), &
714 this%wet_volume_to_mass_mixing_ratio__m3_kg( mode_state ) * &
716 absorp = max( 0.0_musica_dk, absorp )
717 if(
present( max_absorption ) )
then
718 absorp = min( max_absorption(
i_band ), absorp )
733 number_of_coefficients, coefficients, size_function, optics_lookup )
736 use musica_math,
only : weighted_chebyshev
741 class(
mode_t),
intent(in) :: this
745 integer,
intent(in) :: number_of_bands
747 integer,
intent(in) :: number_of_coefficients
749 real(kind=musica_dk),
intent(in) :: coefficients( number_of_coefficients, &
752 real(kind=musica_dk),
intent(in) :: size_function( number_of_coefficients )
754 class(optics_lookup_t),
intent(in) :: optics_lookup
757 real(kind=musica_dk) :: surf_rad
759 surf_rad = this%wet_surface_mode_radius__m( mode_state )
760 if( surf_rad .le. optics_lookup%maximum_radius__m( ) )
then
761 do i_band = 1, number_of_bands
763 ext = weighted_chebyshev( number_of_coefficients, &
764 coefficients( :,
i_band ), &
772 / ( surf_rad * kwaterdensitystp )
778 * this%wet_volume_to_mass_mixing_ratio__m3_kg( mode_state ) &
788 number_of_coefficients, coefficients, size_function )
791 use musica_math,
only : weighted_chebyshev
796 class(
mode_t),
intent(in) :: this
800 integer,
intent(in) :: number_of_bands
802 integer,
intent(in) :: number_of_coefficients
804 real(kind=musica_dk),
intent(in) :: coefficients( number_of_coefficients, &
807 real(kind=musica_dk),
intent(in) :: size_function( number_of_coefficients )
811 do i_band = 1, number_of_bands
813 asym = weighted_chebyshev( number_of_coefficients, &
814 coefficients( :,
i_band ), &
832 raw_size = 2 +
size( this%mass_mixing_ratio__kg_kg_ )
842 real(kind=musica_dk),
intent(in) :: raw_state(:)
843 integer,
optional,
intent(inout) :: index
845 integer :: id, last_id
848 if(
present( index ) ) id = index
849 this%wet_number_mode_diameter__m_ = raw_state( id )
850 this%number_mixing_ratio__num_mol_ = raw_state( id + 1 )
852 last_id = id +
size( this%mass_mixing_ratio__kg_kg_ ) - 1
853 this%mass_mixing_ratio__kg_kg_(:) = raw_state( id : last_id )
854 if(
present( index ) ) index = last_id + 1
864 real(kind=musica_dk),
intent(inout) :: raw_state(:)
865 integer,
optional,
intent(inout) :: index
867 integer :: id, last_id
870 if(
present( index ) ) id = index
871 raw_state( id ) = this%wet_number_mode_diameter__m_
872 raw_state( id + 1 ) = this%number_mixing_ratio__num_mol_
874 last_id = id +
size( this%mass_mixing_ratio__kg_kg_ ) - 1
875 raw_state( id : last_id ) = this%mass_mixing_ratio__kg_kg_(:)
876 if(
present( index ) ) index = last_id + 1
887 real(kind=musica_dk) :: rand_val
890 call random_number( rand_val )
891 this%wet_number_mode_diameter__m_ = 10.0**( rand_val * 3 - 5 )
892 this%number_mixing_ratio__num_mol_ = 10.0**( rand_val * 6 )
893 do i_species = 1,
size( this%mass_mixing_ratio__kg_kg_ )
894 call random_number( rand_val )
895 this%mass_mixing_ratio__kg_kg_( i_species ) = rand_val * 2.0e-9
Constants used in MAM calculations.
real(kind=musica_dk), parameter kaccellerationbygravity
AccellerationByGravity [m s-2].
real(kind=musica_dk), parameter kwaterdensitystp
Water density at STP [kg m-3].
The mode_t type and related functions.
type(wavelength_grid_t) function longwave_grid(this)
Returns the native longwave optics wavelength grid.
pure complex(kind=musica_dk) function, dimension(number_of_bands) net_longwave_refractive_index(this, mode_state, number_of_bands)
Calculates the net refractive index for the mode based on weighted contributions from constituent spe...
real(kind=musica_dk) elemental function wet_number_mode_radius__m(this, mode_state)
Returns the mode radius [m] of the number distribution for the mode.
subroutine print_state(this, aerosol_state, io_unit)
Outputs the current mode state.
real(kind=musica_dk) elemental function wet_surface_mode_diameter__m(this, mode_state)
Returns the mode diameter [m] of the surface area distribution for the mode.
integer function raw_size(this)
Returns the number of doubles needed to hold the raw mode state.
type(mode_t) function constructor(config)
Constructor of mode_t objects.
real(kind=musica_dk) elemental function wet_number_mode_diameter__m(this, mode_state)
Returns the mode diameter [m] of the number distribution for the mode.
elemental real(kind=musica_dk) function geometric_standard_deviation_of_number_distribution(this, mode_state)
Returns the geometric standard deviation of the number distribution of the mode.
pure real(kind=musica_dk) function, dimension(number_of_bands) specific_absorption__m2_kg(this, mode_state, number_of_bands, number_of_coefficients, coefficients, size_function, max_absorption)
Calculates the specific absorption [m2 kg-1] for a given Chebyshev function.
subroutine randomize(this)
Set the mode state to a random, but reasonable, state. For testing only.
real(kind=musica_dk) elemental function wet_surface_mode_radius__m(this, mode_state)
Returns the mode radius [m] of the surface area distribution for the mode.
subroutine dump_state(this, raw_state, index)
Dumps the aerosol state into the raw state array.
real(kind=musica_dk) elemental function number_mixing_ratio__num_mol(this, mode_state)
Returns the particle number mixing ratio per mole air [# mol-1].
pure real(kind=musica_dk) function, dimension(number_of_bands) specific_extinction__m2_kg(this, mode_state, number_of_bands, number_of_coefficients, coefficients, size_function, optics_lookup)
Calculates the specific extinction [m2 kg-1] for a given Chebyshev function.
subroutine shortwave_optics_array(this, environmental_state, aerosol_state, optics)
Returns shortwave optical properties.
class(aerosol_state_t) function, pointer new_state(this)
Creates a new state object for the mode.
pure complex(kind=musica_dk) function, dimension(number_of_bands) net_shortwave_refractive_index(this, mode_state, number_of_bands)
Calculates the net refractive index for the mode based on weighted contributions from constituent spe...
subroutine shortwave_optics_scalar(this, environmental_state, aerosol_state, optics)
Returns shortwave optical properties.
subroutine add_shortwave_optics(this, environmental_state, mode_state, optics)
Calculates shortwave optical properties for a given state and adds them to the set of optical propert...
type(wavelength_grid_t) function shortwave_grid(this)
Returns the native shortwave optics wavelength grid.
subroutine longwave_optics_scalar(this, environmental_state, aerosol_state, optics)
Returns longwave optical properties.
class(optics_t) function, pointer new_optics(this, property, output_grid, interpolation_strategy)
Creates an optics_t object for a given property.
subroutine add_longwave_optics(this, environmental_state, mode_state, optics)
Calculates longwave optical properties for a given state and adds them to the set of optical properti...
subroutine load_state(this, raw_state, index)
Loads raw mode state data to the mode_state_t object.
elemental real(kind=musica_dk) function geometric_mean_diameter_of_number_distribution__m(this, mode_state)
Returns the geometric mean diameter [m] of the number distribution of the mode.
elemental real(kind=musica_dk) function wet_volume_to_mass_mixing_ratio__m3_kg(this, mode_state)
Returns the wet volume to mass mixing ratio for the mode [m3 kg_dryair-1].
subroutine longwave_optics_array(this, environmental_state, aerosol_state, optics)
Returns longwave optical properties.
The optics_lookup_t type and related functions.
Constants used to calculate MAM optical properties.
class(optics_t) function, pointer, public create_optics(property, native_shortwave_grid, native_longwave_grid, output_grid, interpolation_strategy)
Returns an optics_t object for a given property.
subroutine, public add_shortwave_property(extinction_optical_depth, single_scatter_albedo, asymmetry_factor, optics)
Adds to shortwave property values.
subroutine, public add_longwave_property(extinction_optical_depth, optics)
Adds to longwave property values.
The species_t type and related functions.
real(kind=musica_dk), dimension(:,:), intent(out), optional asymmetry_factor
real(kind=musica_dk), dimension(:,:), intent(out), optional absorption
real(kind=musica_dk), dimension(:,:), intent(out), optional extinction