(j3.2006) How to assign to the declared-type part of a polymorphic allocatable array?
Van Snyder
Van.Snyder
Thu Sep 22 16:46:22 EDT 2016
Here's an ugly solution, that gets uglier and uglier as more extensions
of a type are created:
On Wed, 2016-09-21 at 19:57 -0700, Van Snyder wrote:
> Is there a way to assign to the declared-type part of a polymorphic
> allocatable array, other than one component at a time?
>
> I have a type H_t (for horizontal geolocation) that contains latitude
> and longitude. It's agnostic whether the latitude is geocentric or
> geodetic. It has extensions H_Geoc (for geocentric latitude) and H_Geod
> (for geodetic latitude), H_V_t (including a height component V, agnostic
> whether geocentric or geodetic), H_V_Geoc (geocentric latitude and
> height), H_V_Geod (geodetic latitude and height), and others.
>
> I have an object
>
> class(h_t), allocatable :: Geo(:)
>
> which I allocate
>
> if ( geodetic ) then
> allocate ( h_v_geod :: geo(n) )
> else
> allocate ( h_v_geoc :: geo(n) )
> end if
select type ( geo )
class is ( h_geoc ) ! h_v_geoc is an extension of h_geoc
geo%h_t = z%ZOT_to_geo()
class is ( h_geod ) ! h_v_geod is an extension of h_geod
geo%h_t = z%ZOT_to_geo()
end select
I can't use a class default block because therein the declared type of
geo would be h_t, and it wouldn't have a nonpolymorphic h_t component to
which I can assign.
> I then want to fill the horizontal geolocations by applying an elemental
> type-bound function to an array of a type ZOT_t, from which latitudes
> and longitudes are computed. The type ZOT_t represents a uniform
> triangular grid on a (-1:1 X -1:1) square, which is then projected by a
> zenitial orthogonal transformation onto a sphere. The grid is developed
> to a specified refinement, without regard to whether latitudes computed
> from it will be ultimately interpreted as geocentric or geodetic.
> Therefore, the result of the type-bound function ZOT_to_Geo is
> type(H_t), not class(H_t). So after allocating Geo, I'd like to assign
> to its horizontal geolocation components using
>
> geo%h_t = z%ZOT_to_geo()
>
> (size(z) == n) but we've only provided for a parent component, not a
> "self" component, so geo%h_t doesn't exist. I can't use
>
> geo = z%ZOT_to_geo()
>
> for two reasons. First, geo is polymorphic. Second, it has a "v"
> component, that I'm not yet ready to fill.
>
> Is there something simpler than this:
>
> block
> type(h_t) :: T
> integer :: I
> do i = 1, n
> t = z(i)%ZOT_to_geo()
> geo(i)%lat = t%lat
> geo(i)%lon = g%lon
> end do
> end block
>
> Ignoring for a while the "v" component of h_v_geod, I tried
>
> allocate ( geo, source=h_geod(h_t=z%zot_to_geo()) )
>
> but that doesn't work because structure constructors aren't elemental
> (how could they be?). Maybe I could overload h_geod with an elemental
> function; I haven't tried that yet.
>
> I tried
>
> allocate ( h_geod :: geo, source = z%zot_to_geo() )
>
> but that doesn't work because it has both a type spec and a source.
>
> I did finally make this work, but it seems like a needlessly wordy
> kludge:
>
> allocate ( geo, source = [ ( h_v_geod(h_t=z(i)%zot_to_geo(),v=0), i = 1, n ) ] )
>
> Isn't there something simpler?
>
> [BTW, it doesn't work with ifort 15.0.2.164. It complains about a
> missing field [LAT] not being initialized. Maybe it's been repaired
> already. I have not yet been able to convince our SA to install the
> latest Intel release.]
>
>
> _______________________________________________
> J3 mailing list
> J3 at mailman.j3-fortran.org
> http://mailman.j3-fortran.org/mailman/listinfo/j3
More information about the J3
mailing list