forked from MetOffice/lfric_core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmesh_mod.F90
More file actions
4111 lines (3363 loc) · 170 KB
/
Copy pathmesh_mod.F90
File metadata and controls
4111 lines (3363 loc) · 170 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
!-----------------------------------------------------------------------------
! Copyright (c) 2017, Met Office, on behalf of HMSO and Queen's Printer
! For further details please refer to the file LICENCE which you
! should have received as part of this distribution.
!-----------------------------------------------------------------------------
!> @brief Local 3D mesh object.
!>
!> This module provides details for a mesh_type which is generated using a
!> local_mesh object along with some inputs that describe the vertical
!> structure.
!>
!> It also contains a static mesh object for unit testing. This is returned
!> if a mesh_object is instantiated with an integer argument and a local mesh.
!>
module mesh_mod
use constants_mod, only : i_def, r_def, l_def, str_def, &
pi, imdi
use domain_mod, only : domain_type
use extrusion_mod, only : extrusion_type
use lfric_mpi_mod, only : global_mpi
use linked_list_mod, only : linked_list_type, &
linked_list_item_type
use linked_list_data_mod, only : linked_list_data_type
use local_mesh_map_mod, only : local_mesh_map_type
use local_mesh_mod, only : local_mesh_type
use log_mod, only : log_event, log_scratch_space, &
LOG_LEVEL_ERROR, LOG_LEVEL_TRACE, &
LOG_LEVEL_INFO, LOG_LEVEL_DEBUG
use mesh_colouring_mod, only : set_colours
use mesh_tiling_mod, only : set_tiling
use mesh_constructor_helper_functions_mod, &
only : mesh_extruder, &
mesh_connectivity, &
set_dz
use mesh_map_mod, only : mesh_map_type
use mesh_map_collection_mod, only : mesh_map_collection_type
use partition_mod, only : partition_type
use reference_element_mod, only : reference_element_type, &
reference_prism_type, &
reference_cube_type
implicit none
private
!============================================================================
! Declare type definitions in this module
!============================================================================
type, extends(linked_list_data_type), public :: mesh_type
private
!> Mesh name
character(str_def) :: mesh_name
!> Describes the shape of an element on this mesh.
class(reference_element_type), allocatable :: reference_element
!> The local_mesh object that describes the local mesh this mesh
!> is built on
type(local_mesh_type), pointer :: local_mesh
!> The domain limits (x,y,z) for Cartesian domains
!> (long, lat, radius) for spherical
type(domain_type) :: domain
!> Number of 3d-cell layers in mesh object
integer(i_def) :: nlayers
!> Top of atmosphere above surface
real(r_def) :: domain_depth
!> Base surface height
! (0.0 for planar meshes, scaled_radius for cubedsphere)
real(r_def) :: domain_base_height
!> Label for the type of extrusion the mesh has
integer(i_def) :: extrusion_id
!> Non-dimensional vertical coordinate eta[0,1], eta(0:nlayers)
real(r_def), allocatable :: eta(:)
!> Depth of 3d-cell layer [m], dz(nlayers)
real(r_def), allocatable :: dz(:)
!> Vertex Coordinates
!> The x-, y- and z-coordinates of vertices on the mesh [m]
real(r_def), allocatable :: vertex_coords(:,:)
!> Cell-centre Coordinates
!> The x-, y- and z-coordinates of the centres of cells in the mesh
real(r_def), allocatable :: cell_centre_coords(:,:)
!==========================================================================
! Mesh properties:
!==========================================================================
! Local partition base level
integer(i_def) :: nverts_2d !< Number of verts in partition
integer(i_def) :: nedges_2d !< Number of edges in partition
integer(i_def) :: ncells_2d !< Number of cells in partition
integer(i_def) :: ncells_2d_with_ghost !< Number of cells in partition
!< @b including ghost cells
integer(i_def) :: nverts_per_2d_cell ! Number of vertices per face
integer(i_def) :: nverts_per_edge ! Number of vertices per edge
integer(i_def) :: nedges_per_2d_cell ! Number of edges per face
! Local partition 3d-mesh
integer(i_def) :: nverts !< Total number of verts in mesh
integer(i_def) :: nedges !< Total number of edges in mesh
integer(i_def) :: nfaces !< Total number of faces in mesh
integer(i_def) :: ncells !< Total number of cells in mesh
!< @b excluding ghost cells
integer(i_def) :: ncells_with_ghost !< Total number of cells in mesh
!< @b including ghost cells
! 3D-element properties
integer(i_def) :: nverts_per_cell !< Number of verts on 3d-cell
integer(i_def) :: nedges_per_cell !< Number of edges on 3d-cell
integer(i_def) :: nfaces_per_cell !< Number of faces on 3d-cell
!==========================================================================
! Connectivities
!==========================================================================
! All vertex, edge, face and cell id numbers for connectivitivies are
! LOCAL (lid) unless explicitly stated in the variable name,
! i.e. gid (GLOBAL id numbers)
! All connectivity arrays are in the form (ids of entities, cell local id)
! i.e. cell_next(5,6) would hold the local id of the cell adjacent to
! face-5 of 3d-cell with local id = 6. Face-5 of a 3d-cell is the
! bottom so would be the 3d-cell directly below.
! For 3d-mesh
!> Cell ids of adjacent cells
integer(i_def), allocatable :: cell_next (:,:)
!> Vertex ids on cell
integer(i_def), allocatable :: vert_on_cell (:,:)
!> Face ids on cell
integer(i_def), allocatable :: face_on_cell (:,:)
!> Edge ids on cell
integer(i_def), allocatable :: edge_on_cell (:,:)
!> The cell that "owns" the vertex entities around each cell
integer(i_def), allocatable :: vert_cell_owner(:,:)
!> The cell that "owns" the edge entities around each cell
integer(i_def), allocatable :: edge_cell_owner(:,:)
!> The rank of the partition that "owns" the
!> vertex entities around each cell
integer(i_def), allocatable :: vertex_ownership(:,:)
!> The rank of the partition that "owns" the
!> edge entities around each cell
integer(i_def), allocatable :: edge_ownership(:,:)
!> Local index of face in adjacent cells
integer(i_def), allocatable :: face_id_in_adjacent_cell(:,:)
!==========================================================================
! Colouring storage: these form the arguments to set_colours().
!==========================================================================
!> integer, the number of colours
integer(i_def), private :: ncolours
!> integer 1-d array, how many cells belong to each colour
integer(i_def), allocatable, private :: ncells_per_colour(:)
!> integer 2-d array, which cells are in each colour.
integer(i_def), allocatable, private :: cells_in_colour(:,:)
!> integer 2-d array, how many of the first so many cells belong to each colour
integer(i_def), allocatable, private :: ncells_per_colour_subset(:,:)
integer(i_def),allocatable :: last_inner_cell_per_colour(:,:)
integer(i_def),allocatable :: last_halo_cell_per_colour(:,:)
integer(i_def),allocatable :: last_edge_cell_per_colour(:)
!==========================================================================
! Maps that this mesh connects to
!
type(mesh_map_collection_type), allocatable :: mesh_maps
!==========================================================================
! Tiling storage
!==========================================================================
!> The number of colours used for tiling
integer(i_def) :: ntilecolours
!> The number of tiles that belong to each colour
integer(i_def), allocatable :: ntiles_per_colour(:)
!> The number of cells that belong to each coloured tile
integer(i_def), allocatable :: ncells_per_coloured_tile(:,:)
!> Which cells belong to which coloured tile
integer(i_def), allocatable :: cells_in_coloured_tile(:,:,:)
!> How many tiles include cells up to a given halo or partition edge
integer(i_def), allocatable :: last_inner_tile_per_colour(:,:)
integer(i_def), allocatable :: last_edge_tile_per_colour(:)
integer(i_def), allocatable :: last_halo_tile_per_colour(:,:)
!> How many cells in a tile are inside a given halo or partition edge
integer(i_def), allocatable :: last_inner_cell_per_coloured_tile(:,:,:)
integer(i_def), allocatable :: last_halo_cell_per_coloured_tile(:,:,:)
integer(i_def), allocatable :: last_edge_cell_per_coloured_tile(:,:)
contains
procedure, public :: get_reference_element
procedure, public :: get_mesh_name
procedure, public :: get_local_mesh
procedure, public :: get_nlayers
procedure, public :: get_ncells_2d
procedure, public :: get_ncells_2d_with_ghost
procedure, public :: get_nedges_2d
procedure, public :: get_nverts_2d
procedure, public :: get_ncells
procedure, public :: get_nverts
procedure, public :: get_nedges
procedure, public :: get_nfaces
procedure, public :: get_vert_coords
procedure, public :: get_cell_centre_coords
procedure, public :: get_cell_coords
procedure, public :: get_column_coords
procedure, public :: get_nverts_per_cell
procedure, public :: get_nverts_per_cell_2d
procedure, public :: get_nverts_per_edge
procedure, public :: get_nedges_per_cell
procedure, public :: get_nedges_per_cell_2d
procedure, public :: get_nfaces_per_cell
procedure, public :: get_cell_next
procedure, public :: get_face_on_cell
procedure, public :: get_edge_on_cell
procedure, public :: get_vert_on_cell
procedure, public :: get_domain
procedure, public :: get_domain_top
procedure, public :: get_extrusion_id
procedure, public :: get_dz
procedure, public :: get_eta
procedure, public :: get_vertex_cell_owner
procedure, public :: get_edge_cell_owner
procedure, public :: is_vertex_owned
procedure, public :: is_edge_owned
procedure, public :: is_cell_owned
procedure, public :: is_geometry_spherical
procedure, public :: is_geometry_planar
procedure, public :: is_topology_non_periodic
procedure, public :: is_topology_channel
procedure, public :: is_topology_periodic
procedure, public :: is_coord_sys_xyz
procedure, public :: is_coord_sys_ll
procedure, public :: get_num_edges_owned_2d
procedure, public :: get_num_verts_owned_2d
procedure, public :: get_inner_depth
procedure, public :: get_num_cells_inner
procedure, public :: get_last_inner_cell
procedure, public :: get_last_inner_cell_per_colour
procedure, public :: get_last_inner_cell_all_colours
procedure, public :: get_last_inner_tile_per_colour
procedure, public :: get_last_inner_tile_all_colours
procedure, public :: get_last_inner_cell_per_colour_and_tile
procedure, public :: get_last_inner_cell_all_colours_all_tiles
procedure, public :: get_num_cells_edge
procedure, public :: get_last_edge_cell
procedure, public :: get_last_edge_cell_per_colour
procedure, public :: get_last_edge_cell_all_colours
procedure, public :: get_last_edge_tile_per_colour
procedure, public :: get_last_edge_tile_all_colours
procedure, public :: get_last_edge_cell_per_colour_and_tile
procedure, public :: get_last_edge_cell_all_colours_all_tiles
procedure, public :: get_halo_depth
procedure, public :: get_num_cells_halo
procedure, public :: get_last_halo_cell_any
procedure, public :: get_last_halo_cell_deepest
generic :: get_last_halo_cell => &
get_last_halo_cell_any, &
get_last_halo_cell_deepest
procedure, public :: get_last_halo_cell_per_colour_any
procedure, public :: get_last_halo_cell_per_colour_deepest
generic :: get_last_halo_cell_per_colour => &
get_last_halo_cell_per_colour_any, &
get_last_halo_cell_per_colour_deepest
procedure, public :: get_last_halo_cell_all_colours
procedure, public :: get_last_halo_cell_all_colours_deepest
procedure, public :: get_last_halo_tile_per_colour_any
procedure, public :: get_last_halo_tile_per_colour_deepest
generic :: get_last_halo_tile_per_colour => &
get_last_halo_tile_per_colour_any, &
get_last_halo_tile_per_colour_deepest
procedure, public :: get_last_halo_tile_all_colours
procedure, public :: get_last_halo_tile_all_colours_deepest
procedure, public :: get_last_halo_cell_per_colour_and_tile_any
procedure, public :: get_last_halo_cell_per_colour_and_tile_deepest
generic :: get_last_halo_cell_per_colour_and_tile => &
get_last_halo_cell_per_colour_and_tile_any, &
get_last_halo_cell_per_colour_and_tile_deepest
procedure, public :: get_last_halo_cell_all_colours_all_tiles
procedure, public :: get_last_halo_cell_all_colours_all_tiles_deepest
procedure, public :: get_num_cells_ghost
procedure, public :: get_gid_from_lid
procedure, public :: get_mesh_map
procedure, public :: query_mesh_map
procedure, public :: add_mesh_map
procedure, public :: get_adjacent_face
! Get information about colouring of mesh
procedure, public :: get_ncolours
procedure, public :: get_colours
procedure, public :: get_colour_map
procedure, public :: is_coloured
! Get information about mesh tiling
procedure, public :: get_ntilecolours
procedure, public :: get_tiling
procedure, public :: get_coloured_tiling_map
procedure, public :: debug
procedure, public :: clear
! Destructor
final :: mesh_destructor
end type mesh_type
interface mesh_type
module procedure mesh_constructor
module procedure mesh_constructor_unit_test_data
end interface
! -------------------------------------------------------------------------
! Module parameters
! -------------------------------------------------------------------------
!> Counter variable to keep track of the next mesh id number to uniquely
!! identify each different mesh
integer(i_def), save :: mesh_id_counter = 0
!============================================================================
! Options for horizontal pFUnit test meshes
!============================================================================
!
!> @}
!> @name Horizontal Grid Types for pFunit tests
integer(i_def), parameter, public :: PLANE = 1
integer(i_def), parameter, public :: PLANE_BI_PERIODIC = 2
integer(i_def), parameter, public :: PLANE_TWOD = 3
integer(i_def), parameter, public :: PLANE_TWOD_BI_PERIODIC = 4
!> @}
contains
!============================================================================
!> @brief Constructor for the mesh object
!> @param [in] local_mesh A pointer to a local mesh object holding 2d
!> information about the partitioned mesh
!> @param [in] extrusion Mechnism by which extrusion is to be achieved.
!> @param [in, optional]
!> mesh_name Mesh tag name to use for this mesh. If omitted,
!> the mesh name from the local mesh will be used.
!> @param [in, optional]
!> tile_size Sets tile size to (mxn) cells, activates tiling
!> @param [in, optional]
!> inner_halo_tiles Tile inner halos separately for overlapping
! computation and communication
!> @return 3D-Mesh object based on the list of partitioned
!> cells on the given local mesh
!============================================================================
function mesh_constructor ( local_mesh, &
extrusion, &
mesh_name, &
tile_size, &
inner_halo_tiles ) &
result( self )
implicit none
type(local_mesh_type), intent(in), pointer :: local_mesh
class(extrusion_type), intent(in) :: extrusion
character(str_def), intent(in), optional :: mesh_name
integer(i_def), intent(in), optional :: tile_size(2)
logical(l_def), intent(in), optional :: inner_halo_tiles
type(mesh_type) :: self
! Loop counters
integer(i_def) :: i, j
! Vertices connected to local 2d cell.
integer(i_def), allocatable :: vert_on_cell_2d (:,:)
! Edges connected to local 2d cell.
integer(i_def), allocatable :: edge_on_cell_2d (:,:)
! Local 2d cell connectivity.
integer(i_def), allocatable :: cell_next_2d (:,:)
! Surface Coordinates in [long, lat, radius] (Units: Radians/metres)
real(r_def), allocatable :: vertex_coords_2d(:,:)
real(r_def), allocatable :: cell_centre_coords_2d(:,:)
! ll_coords = True: vertex_coords_2d/cell_centre_coords_2d are in lat,lon coords,
! False: vertex_coords_2d/cell_centre_coords_2d are in x,y coords
logical(l_def) :: ll_coords
character(str_def):: name
! Mesh tiling parameters - these assume defaults if not set
integer(i_def) :: tile_size_xy(2)
logical(l_def) :: sep_inner_halo_tiles
! Get unique id for the mesh
mesh_id_counter = mesh_id_counter+1
call self%set_id( mesh_id_counter )
if (present(mesh_name)) then
name = mesh_name
else
name = local_mesh%get_mesh_name()
end if
self%mesh_name = name
! Instantiate appropriate reference element
select case (local_mesh%get_nverts_per_cell())
case (3)
allocate( self%reference_element, source=reference_prism_type() )
case (4)
allocate( self%reference_element, source=reference_cube_type() )
case default
write( log_scratch_space, &
'("Base mesh with ", I0, " vertices per cell not supported.")' &
) local_mesh%get_nverts_per_cell()
call log_event( log_scratch_space, log_level_error )
end select
self%nverts_per_2d_cell = local_mesh%get_nverts_per_cell()
self%nverts_per_edge = local_mesh%get_nverts_per_edge()
self%nedges_per_2d_cell = local_mesh%get_nedges_per_cell()
self%local_mesh => local_mesh
self%ncells_2d = local_mesh%get_num_cells_in_layer()
self%ncells_2d_with_ghost = self%ncells_2d &
+ local_mesh%get_num_cells_ghost()
self%nlayers = extrusion%get_number_of_layers()
self%ncells = self%ncells_2d * self%nlayers
self%ncells_with_ghost = self%ncells_2d_with_ghost * self%nlayers
self%domain_depth = extrusion%get_atmosphere_top()
self%domain_base_height = extrusion%get_atmosphere_bottom()
self%extrusion_id = extrusion%get_id()
self%ncolours = -1 ! Initialise ncolours to error status
allocate( self%eta ( 0:self%nlayers ) )
allocate( self%dz ( self%nlayers ) )
! Calculate non-dimensional vertical coordinate eta[0,1]
call extrusion%extrude( self%eta )
! Calculate layer depth dz for flat planet surface
call set_dz( self%dz, &
self%eta, &
self%nlayers, &
0.0_r_def, &
self%domain_depth )
! Calculate next-to cells and vertices on cells
allocate( self%cell_next(self%reference_element%get_number_faces(), &
self%ncells_with_ghost) )
allocate( self%vert_on_cell(self%reference_element%get_number_vertices(), &
self%ncells_with_ghost) )
self%nverts_per_cell = 2*self%nedges_per_2d_cell
self%nedges_per_cell = 2*self%nedges_per_2d_cell + self%nverts_per_2d_cell
self%nfaces_per_cell = self%nedges_per_2d_cell + 2
!--------------------------------------------------------------------------
! Now get a list of all unique entities in partition (cells/vertices/edges)
!--------------------------------------------------------------------------
allocate( cell_next_2d (self%nedges_per_2d_cell, self%ncells_2d_with_ghost) )
do i=1, self%ncells_2d_with_ghost
call local_mesh%get_cell_next(i,cell_next_2d(:,i))
end do
! Mesh colouring/tiling is written such that it is expecting 0_i_def for connectivity
! outside the local partition. So need to replace cell_next_2d void values with 0_i_def
where ( cell_next_2d == local_mesh%get_void_cell() ) cell_next_2d = 0_i_def
allocate( vert_on_cell_2d ( self%nverts_per_2d_cell, &
self%ncells_2d_with_ghost ) )
do i=1, self%ncells_2d_with_ghost
do j=1, self%nverts_per_2d_cell
vert_on_cell_2d(j,i) = local_mesh%get_vert_on_cell(j,i)
end do
end do
self%nverts_2d = local_mesh%get_n_unique_vertices()
allocate( &
edge_on_cell_2d (self%nedges_per_2d_cell, self%ncells_2d_with_ghost) )
do i=1, self%ncells_2d_with_ghost
do j=1, self%nedges_per_2d_cell
edge_on_cell_2d(j,i) = local_mesh%get_edge_on_cell(j,i)
end do
end do
self%nedges_2d = local_mesh%get_n_unique_edges()
!--------------------------------------------------------------------------
! Get partition vertices lat-lon-z coords, Note z=surface height
!--------------------------------------------------------------------------
allocate(vertex_coords_2d(3,self%nverts_2d))
vertex_coords_2d = 0.0_r_def
do i=1, self%nverts_2d
! Get coords of vertices
call local_mesh%get_vert_coords(i,vertex_coords_2d(1:2,i))
end do
!--------------------------------------------------------------------------
! Get partition cell-centre lat-lon-z coords, Note z=surface height
!--------------------------------------------------------------------------
allocate(cell_centre_coords_2d(3,self%ncells_2d_with_ghost))
cell_centre_coords_2d = 0.0_r_def
do i=1, self%ncells_2d_with_ghost
! Get coords of cell centres
call local_mesh%get_cell_coords(i,cell_centre_coords_2d(1:2,i))
end do
ll_coords = .false.
if ( local_mesh%is_coord_sys_ll() ) ll_coords = .true.
! Set base surface height
vertex_coords_2d(3,:) = self%domain_base_height
cell_centre_coords_2d(3,:) = self%domain_base_height
self%nverts = self%nverts_2d * (self%nlayers+1)
self%nedges = self%nedges_2d * (self%nlayers+1) &
+ self%nverts_2d*self%nlayers
self%nfaces = self%ncells_2d_with_ghost * (self%nlayers+1) &
+ self%nedges_2d * self%nlayers
allocate ( self%vertex_coords( 3, self%nverts ) )
allocate ( self%cell_centre_coords( 3, self%ncells_with_ghost ) )
call mesh_extruder( self%cell_next, &
self%vert_on_cell, &
self%vertex_coords, &
self%cell_centre_coords, &
self%reference_element%get_number_faces(), &
self%reference_element%get_number_vertices(), &
cell_next_2d, &
vert_on_cell_2d, &
vertex_coords_2d, &
cell_centre_coords_2d, &
ll_coords, &
self%nverts_per_2d_cell, &
self%nedges_per_2d_cell, &
self%nverts_2d, &
self%nverts, &
self%ncells_2d_with_ghost, &
self%ncells_with_ghost, &
self%nlayers, &
self%dz, &
self%reference_element )
allocate( self%face_on_cell( self%nfaces_per_cell, &
self%ncells_2d_with_ghost ) )
allocate( self%edge_on_cell( self%nedges_per_cell, &
self%ncells_2d_with_ghost ) )
call mesh_connectivity( self%face_on_cell, &
self%edge_on_cell, &
self%ncells_2d_with_ghost, &
self%nfaces_per_cell, &
self%nedges_per_cell, &
self%cell_next, &
self%vert_on_cell, &
self%reference_element )
self%domain = domain_type( local_mesh%get_global_domain_extents(), &
self%domain_base_height, &
self%domain_depth, ll_coords )
deallocate (vert_on_cell_2d)
deallocate (edge_on_cell_2d)
deallocate (cell_next_2d)
deallocate (vertex_coords_2d)
deallocate (cell_centre_coords_2d)
! Assign ownership of cell vertices and cell edges
allocate( &
self%vertex_ownership (self%nverts_per_2d_cell, self%ncells_2d_with_ghost) )
allocate( &
self%edge_ownership (self%nedges_per_2d_cell, self%ncells_2d_with_ghost) )
allocate( &
self%vert_cell_owner (self%nverts_per_2d_cell, self%ncells_2d_with_ghost) )
allocate( &
self%edge_cell_owner (self%nedges_per_2d_cell, self%ncells_2d_with_ghost) )
do i=1, self%ncells_2d_with_ghost
! Vertex ownership
do j=1, self%nverts_per_2d_cell
self%vert_cell_owner(j,i) = &
local_mesh%get_vert_cell_owner(local_mesh%get_vert_on_cell(j,i))
if (self%vert_cell_owner(j,i) > 0) then
self%vertex_ownership(j,i) = local_mesh%get_cell_owner( &
self%vert_cell_owner(j,i) )
else
self%vertex_ownership(j,i) = global_mpi%get_comm_size() + 1
end if
end do
! Edge ownership
do j=1, self%nedges_per_2d_cell
self%edge_cell_owner(j,i) = &
local_mesh%get_edge_cell_owner(local_mesh%get_edge_on_cell(j,i))
if (self%edge_cell_owner(j,i) > 0) then
self%edge_ownership(j,i) = local_mesh%get_cell_owner( &
self%edge_cell_owner(j,i) )
else
self%edge_ownership(j,i) = global_mpi%get_comm_size() + 1
end if
end do
end do
if (.not. allocated(self%mesh_maps) ) &
allocate ( self%mesh_maps, source = mesh_map_collection_type() )
if ( .not. allocated(self%face_id_in_adjacent_cell) ) &
allocate ( self%face_id_in_adjacent_cell( self%nedges_per_2d_cell, &
self%ncells_2d_with_ghost) )
call calc_face_id_in_adjacent_cell( &
self%face_id_in_adjacent_cell, &
self%reference_element%get_number_horizontal_faces(), &
self%cell_next, &
self%reference_element%get_number_faces(), &
self%ncells_2d_with_ghost )
call set_colours( self%get_ncells_2d(), &
self%cell_next, &
self%ncolours, &
self%ncells_per_colour, &
self%cells_in_colour, &
self%reference_element%get_number_horizontal_faces(), &
self%local_mesh )
call init_last_cell_per_colour(self)
! Set tiling to 1x1 tile size (equivalent to colouring) by default
if ( present(tile_size) ) then
tile_size_xy = tile_size
else
tile_size_xy = 1
end if
! Tile partition as a whole by default (outer halos are always separated)
if ( present(inner_halo_tiles) ) then
sep_inner_halo_tiles = inner_halo_tiles
else
sep_inner_halo_tiles = .false.
end if
call set_tiling( self%get_ncells_2d(), &
self%cell_next, &
self%local_mesh, &
self%ncolours, &
self%ncells_per_colour, &
self%cells_in_colour, &
tile_size_xy, &
sep_inner_halo_tiles, &
self%ntilecolours, &
self%ntiles_per_colour, &
self%ncells_per_coloured_tile, &
self%cells_in_coloured_tile, &
self%last_inner_tile_per_colour, &
self%last_inner_cell_per_coloured_tile, &
self%last_edge_tile_per_colour, &
self%last_edge_cell_per_coloured_tile, &
self%last_halo_tile_per_colour, &
self%last_halo_cell_per_coloured_tile )
end function mesh_constructor
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> @brief Gets the reference element for this mesh.
!>
function get_reference_element( self )
implicit none
class(mesh_type), intent(in), target :: self
! Return variable
class(reference_element_type), pointer :: get_reference_element
get_reference_element => self%reference_element
end function get_reference_element
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> @brief Gets a pointer to the local_mesh object that was used to
!> create this mesh.
!>
!> @return Pointer to local_mesh object.
!>
function get_local_mesh(self) result(local_mesh)
implicit none
class(mesh_type), target :: self
type(local_mesh_type), pointer :: local_mesh
local_mesh => self%local_mesh
end function get_local_mesh
!============================================================================
! Mesh Type Methods
!============================================================================
!> @details This subrotuine returns 3-element array of vertex coords
!> in cartesian coords [x,y,z] with units in [m].
!> @param[in] vert_lid The local id of the requested vertex
!> @param[out] vertex_coords A three-element array containing the
!> cartesian coordinates of a single vertex
!> in the mesh object
!============================================================================
subroutine get_vert_coords(self, vert_lid, vertex_coords)
! Returns 3-element array of vertex coords in
! cartesian coords [x,y,z] with units in [m].
implicit none
class(mesh_type), intent(in) :: self
integer(i_def), intent(in) :: vert_lid
real(r_def), intent(out) :: vertex_coords(:)
vertex_coords(:) = self%vertex_coords(:,vert_lid)
end subroutine get_vert_coords
!> @details Returns 3-element array of cell-centre coords
!> @param[in] cell_lid The local id of the requested cell
!> @param[out] cell_centre_coords A three-element array containing the
!> coordinates of a the centre of a single
!> cell in the mesh object
!============================================================================
subroutine get_cell_centre_coords(self, cell_lid, cell_centre_coords)
implicit none
class(mesh_type), intent(in) :: self
integer(i_def), intent(in) :: cell_lid
real(r_def), intent(out) :: cell_centre_coords(:)
cell_centre_coords(:) = self%cell_centre_coords(:,cell_lid)
end subroutine get_cell_centre_coords
!> @details This subroutine returns 3-element array of vertex coords for
!> each vertex on the request local cell id. Coords are in
!> cartesian coords [x,y,z] in [m] and in same order as the
!> vertex on cell connectivity array
!> @param[in] cell_lid The local id of the requested cell
!> @param[out cell_coords A 2-dimensional array which contains
!> the cartesian coordinates of each vertex
!> on the requested cell_lid. The returned
!> array will have dimensions of
!> [3, nVertices on cell]
!============================================================================
subroutine get_cell_coords(self, cell_lid, cell_coords)
! Returns 3-element array of vertex coords for each
! vertex on the request local cell id. Coords are
! in cartesian coords [x,y,z] in [m] and in same order
! as the vertex on cell connectivity array
implicit none
class(mesh_type), intent(in) :: self
integer(i_def), intent(in) :: cell_lid
real(r_def), intent(out) :: cell_coords(:,:)
integer(i_def) :: ivert, vert_lid
do ivert=1, self%nverts_per_cell
vert_lid = self%vert_on_cell(ivert, cell_lid)
call self%get_vert_coords(vert_lid, cell_coords(:,ivert))
end do
end subroutine get_cell_coords
!> @details This subroutine returns 3-element array of vertex coords
!> for a vertical cell column in the local mesh. Any local
!> cell id within the column can be provided.
!> @param[in] cell_lid The local id of the requested cell
!> @param[out] column_coords A 3-dimensional array which contains the
!> cartesian coordinates of each vertex on the
!> column of 3D-cells which include the requested
!> cell_lid. The returned array will have
!> dimensions of [3, nVertices on cell, nlayers]
!============================================================================
subroutine get_column_coords(self, cell_lid, column_coords)
! Returns 3-element array of vertex coords for a vertical
! cell column in the local mesh. Any local cell id within
! the column can be provided.
implicit none
class(mesh_type), intent(in) :: self
integer(i_def), intent(in) :: cell_lid
real(r_def), intent(out) :: column_coords(:,:,:)
integer(i_def) :: base_id, k, icell
! Get the cell id of the cell at the base of the column containing input cell
base_id = modulo(cell_lid,self%ncells_2d_with_ghost)
if (base_id == 0) base_id = self%ncells_2d_with_ghost
! Get the coordinates of each cell in the column
do k=1, self%nlayers
icell = base_id + (k-1)*self%ncells_2d_with_ghost
call self%get_cell_coords(icell,column_coords(:,:,k))
end do
end subroutine get_column_coords
!> @details This function returns the number of 3d-cell layers in the mesh
!> object
!> @return Number of 3d-cell vertical layers in the mesh object
!============================================================================
function get_nlayers(self) result (nlayers)
! This function returns the number of 3d-cell layers
! in the mesh object
implicit none
class(mesh_type), intent(in) :: self
integer(i_def) :: nlayers
nlayers = self%nlayers
end function get_nlayers
!> @details This function returns the number of
!> vertices per 3d-cell on this mesh
!> @return Number of vertices per 3d-cell on mesh
!============================================================================
function get_nverts_per_cell(self) result (nverts_per_cell)
! Returns number of vertices per 3d-cell on this mesh
implicit none
class (mesh_type), intent(in) :: self
integer(i_def) :: nverts_per_cell
nverts_per_cell = self%nverts_per_cell
end function get_nverts_per_cell
!> @details This function returns the number of
!> vertices per 2d-cell/face on this mesh
!> @return Number of vertices per 2d-cell/face on mesh
!============================================================================
function get_nverts_per_cell_2d(self) result (nverts_per_cell_2d)
! Returns number of vertices per 2d-cell on this mesh
implicit none
class (mesh_type), intent(in) :: self
integer(i_def) :: nverts_per_cell_2d
nverts_per_cell_2d = self%nverts_per_2d_cell
end function get_nverts_per_cell_2d
!> @details This function returns the number of
!> vertices per edge on this mesh
!> @return Number of vertices per edge on mesh
!============================================================================
function get_nverts_per_edge(self) result (nverts_per_edge)
! Returns number of vertices per edge on this mesh
implicit none
class (mesh_type), intent(in) :: self
integer(i_def) :: nverts_per_edge
nverts_per_edge = self%nverts_per_edge
end function get_nverts_per_edge
!> @details This function returns the number of
!> edges per 3d-cell on this mesh
!> @return Number of edges per 3d-cell on mesh
!============================================================================
function get_nedges_per_cell(self) result (nedges_per_cell)
! Returns number of edges per 3d-cell on this mesh
implicit none
class(mesh_type), intent(in) :: self
integer(i_def) :: nedges_per_cell
nedges_per_cell = self%nedges_per_cell
end function get_nedges_per_cell
!> @details This function returns the number of
!> edges per 2d-cell/face on this mesh
!> @return Number of edges per 2d-cell/face on mesh
!============================================================================
function get_nedges_per_cell_2d(self) result (nedges_per_cell_2d)
! Returns number of edges per 2d-cell on this mesh
implicit none
class (mesh_type), intent(in) :: self
integer(i_def) :: nedges_per_cell_2d
nedges_per_cell_2d = self%nedges_per_2d_cell
end function get_nedges_per_cell_2d
!> @details This function returns the number
!> of faces per 3d-cell on this et-mesh
!> @return Number of faces per 3d-cell on mesh
!============================================================================
function get_nfaces_per_cell(self) result (nfaces_per_cell)
! Returns number of faces per 3d-cell on this mesh
implicit none
class(mesh_type), intent(in) :: self
integer(i_def) :: nfaces_per_cell
nfaces_per_cell = self%nfaces_per_cell
end function get_nfaces_per_cell
!> @details Returns local cell id of adjacent cell on the specified face
!> (iface) of the given cell (icell)
!> @param[in] iface The index (on the known cell with local id,
!> @c cell_lid ) of the face common to both cells
!> @param[in] cell_lid The local id of the known cell
!> @return The local id of cell adjacent to the
!> known cell ( @c cell_lid ) with the
!> common face ( @c iface )
!============================================================================
function get_cell_next(self, iface, cell_lid) result (cell_next_lid)
! Returns local cell id of adjacent cell on the
! specified face (iface) of the given cell (cell_lid)
implicit none
class(mesh_type), intent(in) :: self
integer(i_def), intent(in) :: iface ! Index of face required
integer(i_def), intent(in) :: cell_lid ! Local cell id
integer(i_def) :: cell_next_lid
cell_next_lid = self%cell_next(iface, cell_lid)
end function get_cell_next
!> @details This function returns the local face id on local cell
!> @param [in] iface The index face of interest
!> @param [in] icell The local id of the cell which the
!> face is a member of
!> @return The local id of face on index iface
!> of cell with local id icell
!============================================================================
function get_face_on_cell(self, iface, icell) result (face_lid)
! Returns local face id on local cell
implicit none
class(mesh_type), intent(in) :: self
integer(i_def), intent(in) :: iface ! Index of face required
integer(i_def), intent(in) :: icell ! Local cell id
integer(i_def) :: face_lid
face_lid = self%face_on_cell(iface, icell)
end function get_face_on_cell
!> @details This function returns the local edge id on the local cell