source: codes/icosagcm/devel/src/sphere/geometry.f90 @ 856

Last change on this file since 856 was 856, checked in by dubos, 5 years ago

devel : towards Fortran driver for unstructured/LAM meshes

File size: 22.6 KB
Line 
1MODULE geometry
2  USE field_mod
3  IMPLICIT NONE
4
5  TYPE t_geometry
6    TYPE(t_field),POINTER :: centroid(:)
7    TYPE(t_field),POINTER :: xyz_i(:)
8    TYPE(t_field),POINTER :: xyz_e(:)
9    TYPE(t_field),POINTER :: xyz_v(:)
10    TYPE(t_field),POINTER :: lon_i(:)
11    TYPE(t_field),POINTER :: lon_e(:)
12    TYPE(t_field),POINTER :: lat_i(:)
13    TYPE(t_field),POINTER :: lat_e(:)
14    TYPE(t_field),POINTER :: ep_e(:)
15    TYPE(t_field),POINTER :: et_e(:)
16    TYPE(t_field),POINTER :: elon_i(:)
17    TYPE(t_field),POINTER :: elat_i(:)
18    TYPE(t_field),POINTER :: elon_e(:)
19    TYPE(t_field),POINTER :: elat_e(:)
20    TYPE(t_field),POINTER :: Ai(:)
21    TYPE(t_field),POINTER :: Av(:)
22    TYPE(t_field),POINTER :: de(:)
23    TYPE(t_field),POINTER :: le(:)
24    TYPE(t_field),POINTER :: le_de(:) ! le/de, 0. if de=0.
25    TYPE(t_field),POINTER :: Riv(:)
26    TYPE(t_field),POINTER :: S1(:)
27    TYPE(t_field),POINTER :: S2(:)
28    TYPE(t_field),POINTER :: Riv2(:)
29    TYPE(t_field),POINTER :: ne(:)
30    TYPE(t_field),POINTER :: Wee(:)
31    TYPE(t_field),POINTER :: bi(:)
32    TYPE(t_field),POINTER :: fv(:)
33  END TYPE t_geometry   
34
35  TYPE(t_geometry),SAVE,TARGET :: geom
36
37 
38  REAL(rstd),POINTER :: Ai(:)          ! area of a cell
39!$OMP THREADPRIVATE(Ai)
40  REAL(rstd),POINTER :: centroid(:,:)  ! coordinate of the centroid of the cell
41!$OMP THREADPRIVATE(centroid)
42  REAL(rstd),POINTER :: xyz_i(:,:)     ! coordinate of the center of the cell (voronoi)
43!$OMP THREADPRIVATE(xyz_i)
44  REAL(rstd),POINTER :: xyz_e(:,:)     ! coordinate of a wind point on the cell on a edge
45!$OMP THREADPRIVATE(xyz_e)
46  REAL(rstd),POINTER :: xyz_v(:,:)     ! coordinate of a vertex (center of the dual mesh)
47!$OMP THREADPRIVATE(xyz_v)
48  REAL(rstd),POINTER :: lon_i(:)       ! longitude of the center of the cell (voronoi)
49!$OMP THREADPRIVATE(lon_i)
50  REAL(rstd),POINTER :: lon_e(:)       ! longitude of a wind point on the cell on a edge
51!$OMP THREADPRIVATE(lon_e)
52  REAL(rstd),POINTER :: lat_i(:)       ! latitude of the center of the cell (voronoi)
53!$OMP THREADPRIVATE(lat_i)
54  REAL(rstd),POINTER :: lat_e(:)       ! latitude of a wind point on the cell on a edge
55!$OMP THREADPRIVATE(lat_e)
56  REAL(rstd),POINTER :: ep_e(:,:)      ! perpendicular unit vector of a edge (outsider)
57!$OMP THREADPRIVATE(ep_e)
58  REAL(rstd),POINTER :: et_e(:,:)      ! tangeantial unit vector of a edge
59!$OMP THREADPRIVATE(et_e)
60  REAL(rstd),POINTER :: elon_i(:,:)    ! unit longitude vector on the center
61!$OMP THREADPRIVATE(elon_i)
62  REAL(rstd),POINTER :: elat_i(:,:)    ! unit latitude vector on the center
63!$OMP THREADPRIVATE(elat_i)
64  REAL(rstd),POINTER :: elon_e(:,:)    ! unit longitude vector on a wind point
65!$OMP THREADPRIVATE(elon_e)
66  REAL(rstd),POINTER :: elat_e(:,:)    ! unit latitude vector on a wind point
67!$OMP THREADPRIVATE(elat_e)
68  REAL(rstd),POINTER :: Av(:)          ! area of dual mesk cell
69!$OMP THREADPRIVATE(Av)
70  REAL(rstd),POINTER :: de(:)          ! distance from a neighbour == lenght of an edge of the dual mesh
71!$OMP THREADPRIVATE(de)
72  REAL(rstd),POINTER :: le(:)          ! lenght of a edge
73!$OMP THREADPRIVATE(le)
74  REAL(rstd),POINTER :: le_de(:)       ! le/de
75!$OMP THREADPRIVATE(le_de)
76  REAL(rstd),POINTER :: S1(:,:)        ! area of sub-triangle
77!$OMP THREADPRIVATE(S1)
78  REAL(rstd),POINTER :: S2(:,:)        ! area of sub-tirangle
79!$OMP THREADPRIVATE(S2)
80  REAL(rstd),POINTER :: Riv(:,:)       ! weight
81!$OMP THREADPRIVATE(Riv)
82  REAL(rstd),POINTER :: Riv2(:,:)      ! weight
83!$OMP THREADPRIVATE(Riv2)
84  INTEGER,POINTER    :: ne(:,:)        ! convention for the way on the normal wind on an edge
85!$OMP THREADPRIVATE(ne)
86  REAL(rstd),POINTER :: Wee(:,:,:)     ! weight
87!$OMP THREADPRIVATE(Wee)
88  REAL(rstd),POINTER :: bi(:)          ! orographie
89!$OMP THREADPRIVATE(bi)
90  REAL(rstd),POINTER :: fv(:)          ! coriolis (evaluted on a vertex)
91!$OMP THREADPRIVATE(fv)
92     
93
94  INTEGER, PARAMETER :: ne_right=1
95  INTEGER, PARAMETER :: ne_rup=-1
96  INTEGER, PARAMETER :: ne_lup=1
97  INTEGER, PARAMETER :: ne_left=-1
98  INTEGER, PARAMETER :: ne_ldown=1
99  INTEGER, PARAMETER :: ne_rdown=-1
100
101CONTAINS
102
103  SUBROUTINE allocate_geometry
104  USE field_mod
105  IMPLICIT NONE
106 
107    CALL allocate_field(geom%Ai,field_t,type_real,name='Ai')
108
109    CALL allocate_field(geom%xyz_i,field_t,type_real,3)
110    CALL allocate_field(geom%lon_i,field_t,type_real)
111    CALL allocate_field(geom%lat_i,field_t,type_real)
112    CALL allocate_field(geom%elon_i,field_t,type_real,3)
113    CALL allocate_field(geom%elat_i,field_t,type_real,3)
114    CALL allocate_field(geom%centroid,field_t,type_real,3)
115
116    CALL allocate_field(geom%xyz_e,field_u,type_real,3)
117    CALL allocate_field(geom%lon_e,field_u,type_real)
118    CALL allocate_field(geom%lat_e,field_u,type_real)
119    CALL allocate_field(geom%elon_e,field_u,type_real,3)
120    CALL allocate_field(geom%elat_e,field_u,type_real,3)
121    CALL allocate_field(geom%ep_e,field_u,type_real,3)
122    CALL allocate_field(geom%et_e,field_u,type_real,3)
123
124    CALL allocate_field(geom%xyz_v,field_z,type_real,3)
125    CALL allocate_field(geom%de,field_u,type_real)
126    CALL allocate_field(geom%le,field_u,type_real)
127    CALL allocate_field(geom%le_de,field_u,type_real)
128    CALL allocate_field(geom%bi,field_t,type_real)
129    CALL allocate_field(geom%Av,field_z,type_real)
130    CALL allocate_field(geom%S1,field_t,type_real,6)
131    CALL allocate_field(geom%S2,field_t,type_real,6)
132    CALL allocate_field(geom%Riv,field_t,type_real,6)
133    CALL allocate_field(geom%Riv2,field_t,type_real,6)
134    CALL allocate_field(geom%ne,field_t,type_integer,6)
135    CALL allocate_field(geom%Wee,field_u,type_real,5,2)
136    CALL allocate_field(geom%bi,field_t,type_real)
137    CALL allocate_field(geom%fv,field_z,type_real)
138
139  END SUBROUTINE allocate_geometry
140 
141 
142  SUBROUTINE swap_geometry(ind)
143  USE field_mod
144  USE domain_mod, ONLY : swap_needed
145  IMPLICIT NONE
146    INTEGER,INTENT(IN) :: ind
147
148    IF(.NOT. swap_needed) RETURN
149
150!!$OMP MASTER
151    Ai=geom%Ai(ind)
152    xyz_i=geom%xyz_i(ind)
153    centroid=geom%centroid(ind)
154    xyz_e=geom%xyz_e(ind)
155    ep_e=geom%ep_e(ind)
156    et_e=geom%et_e(ind)
157    lon_i=geom%lon_i(ind)
158    lat_i=geom%lat_i(ind)
159    lon_e=geom%lon_e(ind)
160    lat_e=geom%lat_e(ind)
161    elon_i=geom%elon_i(ind)
162    elat_i=geom%elat_i(ind)
163    elon_e=geom%elon_e(ind)
164    elat_e=geom%elat_e(ind)
165    xyz_v=geom%xyz_v(ind)
166    de=geom%de(ind)
167    le=geom%le(ind)
168    le_de=geom%le_de(ind)
169    Av=geom%Av(ind)
170    S1=geom%S1(ind)
171    S2=geom%S2(ind)
172    Riv=geom%Riv(ind)
173    Riv2=geom%Riv2(ind)
174    ne=geom%ne(ind)
175    Wee=geom%Wee(ind)
176    bi=geom%bi(ind)
177    fv=geom%fv(ind)
178!!$OMP END MASTER
179!!$OMP BARRIER   
180  END SUBROUTINE swap_geometry
181
182  SUBROUTINE update_circumcenters 
183    USE domain_mod
184    USE dimensions
185    USE spherical_geom_mod
186    USE vector
187    USE transfert_mod
188    USE omp_para
189
190    IMPLICIT NONE
191    REAL(rstd) :: x1(3),x2(3)
192    REAL(rstd) :: vect(3,6)
193    REAL(rstd) :: centr(3)
194    INTEGER :: ind,i,j,n,k
195    TYPE(t_message),SAVE :: message0, message1
196    LOGICAL, SAVE :: first=.TRUE.
197!$OMP THREADPRIVATE(first)   
198   
199    IF (first) THEN
200      CALL init_message(geom%xyz_i, req_i0 ,message0)
201      CALL init_message(geom%xyz_i, req_i1 ,message1)
202      first=.FALSE.
203    ENDIF
204   
205    CALL transfert_message(geom%xyz_i,message0)
206    CALL transfert_message(geom%xyz_i,message1)
207   
208    DO ind=1,ndomain
209      IF (.NOT. assigned_domain(ind) .OR. .NOT. is_omp_level_master) CYCLE
210      CALL swap_dimensions(ind)
211      CALL swap_geometry(ind)
212      DO j=jj_begin,jj_end
213        DO i=ii_begin,ii_end
214          n=(j-1)*iim+i
215          DO k=0,5
216            x1(:) = xyz_i(n+t_pos(k+1),:)
217            x2(:) = xyz_i(n+t_pos(MOD(k+1,6)+1),:)
218            if (norm(x1-x2)<1e-16) x2(:) = xyz_i(n+t_pos(MOD(k+2,6)+1),:)
219            CALL circumcenter(xyz_i(n,:), x1, x2, xyz_v(n+z_pos(k+1),:))
220          ENDDO
221        ENDDO
222      ENDDO
223    ENDDO
224
225  END SUBROUTINE update_circumcenters
226
227  SUBROUTINE remap_schmidt_loc
228    USE spherical_geom_mod
229    USE getin_mod
230    USE omp_para
231    USE domain_mod
232    USE dimensions
233    IMPLICIT NONE
234    INTEGER :: ind,i,j,n
235    REAL(rstd) :: schmidt_factor, schmidt_lon, schmidt_lat
236
237    ! Schmidt transform parameters
238    schmidt_factor = 1.
239    CALL getin('schmidt_factor', schmidt_factor)
240    schmidt_factor =  schmidt_factor**2.
241   
242    schmidt_lon = 0.
243    CALL getin('schmidt_lon', schmidt_lon)
244    schmidt_lon = schmidt_lon * pi/180.
245
246    schmidt_lat = 45.
247    CALL getin('schmidt_lat', schmidt_lat)
248    schmidt_lat = schmidt_lat * pi/180.
249
250    DO ind=1,ndomain
251      IF (.NOT. assigned_domain(ind) .OR. .NOT. is_omp_level_master) CYCLE
252      CALL swap_dimensions(ind)
253      CALL swap_geometry(ind)
254      DO j=jj_begin,jj_end
255        DO i=ii_begin,ii_end
256          n=(j-1)*iim+i
257          CALL schmidt_transform(xyz_i(n,:), schmidt_factor, schmidt_lon, schmidt_lat)
258        ENDDO
259      ENDDO
260    ENDDO
261  END SUBROUTINE remap_schmidt_loc
262
263  SUBROUTINE optimize_geometry
264  USE metric
265  USE spherical_geom_mod
266  USE domain_mod
267  USE dimensions
268  USE transfert_mod
269  USE vector
270  USE getin_mod
271  USE omp_para
272  IMPLICIT NONE
273    INTEGER :: nb_it=0
274    TYPE(t_domain),POINTER :: d
275    INTEGER :: ind,it,i,j,n,k
276    REAL(rstd) :: x1(3),x2(3)
277    REAL(rstd) :: vect(3,6)
278    REAL(rstd) :: centr(3)
279    REAL(rstd) :: sum
280    LOGICAL    :: check
281   
282   
283    CALL getin('optim_it',nb_it)
284   
285    DO ind=1,ndomain
286      IF (.NOT. assigned_domain(ind)  .OR. .NOT. is_omp_level_master) CYCLE
287      d=>domain(ind)
288      CALL swap_dimensions(ind)
289      CALL swap_geometry(ind)
290      xyz_i(:,1) = 0 ; xyz_i(:,2) = 0 ;  xyz_i(:,3) = 1
291     
292      DO j=jj_begin,jj_end
293        DO i=ii_begin,ii_end
294          n=(j-1)*iim+i
295          xyz_i(n,:)=d%xyz(:,i,j) 
296        ENDDO
297      ENDDO
298    ENDDO
299   
300    CALL update_circumcenters
301
302    DO ind=1,ndomain
303      IF (.NOT. assigned_domain(ind)  .OR. .NOT. is_omp_level_master ) CYCLE
304      d=>domain(ind)
305      CALL swap_dimensions(ind)
306      CALL swap_geometry(ind)
307      DO j=jj_begin,jj_end
308        DO i=ii_begin,ii_end
309          n=(j-1)*iim+i
310          DO k=0,5
311            x1(:) = xyz_v(n+z_pos(k+1),:)
312            x2(:) = d%vertex(:,k,i,j) 
313            IF (norm(x1-x2)>1e-10) THEN
314              PRINT*,"vertex diff ",ind,i,j,k
315              PRINT*,x1
316              PRINT*,x2
317            ENDIF
318          ENDDO
319        ENDDO
320      ENDDO
321    ENDDO
322   
323   
324    DO it=1,nb_it
325      IF (MOD(it,100)==0) THEN
326        check=is_master
327      ELSE
328        check=.FALSE.
329      ENDIF
330     
331      sum=0
332      DO ind=1,ndomain
333      IF (.NOT. assigned_domain(ind)  .OR. .NOT. is_omp_level_master ) CYCLE
334        CALL swap_dimensions(ind)
335        CALL swap_geometry(ind)
336        DO j=jj_begin,jj_end
337          DO i=ii_begin,ii_end
338            n=(j-1)*iim+i
339            vect(:,1)=xyz_v(n+z_rup,:)
340            vect(:,2)=xyz_v(n+z_up,:)
341            vect(:,3)=xyz_v(n+z_lup,:)
342            vect(:,4)=xyz_v(n+z_ldown,:)
343            vect(:,5)=xyz_v(n+z_down,:)
344            vect(:,6)=xyz_v(n+z_rdown,:)
345            CALL compute_centroid(vect,6,centr)
346            IF (check) THEN
347              sum=MAX(sum,norm(xyz_i(n,:)-centr(:)))
348            ENDIF
349            xyz_i(n,:)=centr(:)
350          ENDDO
351        ENDDO
352       
353      ENDDO
354
355      IF (check) PRINT *,"it = ",it,"  diff centroid circumcenter ",sum
356
357     CALL update_circumcenters
358
359    ENDDO
360   
361  END SUBROUTINE optimize_geometry
362
363  SUBROUTINE update_domain 
364    ! copy position of generators and vertices back into domain(:)%xyz/vertex
365    ! so that XIOS/create_header_gen gets the right values
366    USE omp_para
367    USE dimensions
368    USE domain_mod 
369    USE transfert_mpi_mod
370
371    INTEGER :: ind,i,j,k,n
372    TYPE(t_domain),POINTER :: d
373    TYPE(t_field),POINTER,SAVE :: xyz_glo(:), xyz_loc(:), vertex_glo(:), vertex_loc(:)
374    REAL(rstd), POINTER :: xyz(:,:), vertex(:,:)
375   
376    CALL allocate_field(xyz_loc, field_t, type_real, 3)
377    CALL allocate_field(vertex_loc, field_z, type_real, 3)
378
379    DO ind=1,ndomain
380       IF (.NOT. assigned_domain(ind)  .OR. .NOT. is_omp_level_master ) CYCLE
381       CALL swap_dimensions(ind)
382       CALL swap_geometry(ind)
383       xyz = xyz_loc(ind)
384       xyz(:,:) = xyz_i(:,:)
385       vertex = vertex_loc(ind)
386       vertex(:,:) = xyz_v(:,:)
387    END DO
388
389!$OMP BARRIER   
390!$OMP MASTER
391    CALL allocate_field_glo(xyz_glo, field_t, type_real, 3)
392    CALL allocate_field_glo(vertex_glo, field_z, type_real, 3)
393
394    CALL gather_field(xyz_loc, xyz_glo)
395    CALL gather_field(vertex_loc, vertex_glo)
396
397    CALL bcast_field(xyz_glo)
398    CALL bcast_field(vertex_glo)
399
400    DO ind=1,ndomain_glo
401       d=>domain_glo(ind)
402       xyz = xyz_glo(ind)
403       vertex = vertex_glo(ind)
404       DO j=d%jj_begin,d%jj_end
405          DO i=d%ii_begin,d%ii_end         
406             n=(j-1)*d%iim+i
407             d%xyz(:,i,j)=xyz(n,:)
408             DO k=0,5
409                d%vertex(:,k,i,j) = vertex(n+d%z_pos(k+1),:)
410             END DO
411          END DO
412       END DO
413    END DO
414
415    CALL deallocate_field_glo(vertex_glo)
416    CALL deallocate_field_glo(xyz_glo)
417!$OMP END MASTER
418!$OMP BARRIER
419    CALL deallocate_field(vertex_loc)
420    CALL deallocate_field(xyz_loc)
421
422  END SUBROUTINE update_domain
423 
424  SUBROUTINE set_geometry
425  USE metric
426  USE vector
427  USE spherical_geom_mod
428  USE domain_mod
429  USE dimensions
430  USE transfert_mod
431  USE getin_mod
432  USE omp_para
433  IMPLICIT NONE
434
435    REAL(rstd) :: surf(6)
436    REAL(rstd) :: surf_v(6)
437    REAL(rstd) :: vect(3,6)
438    REAL(rstd) :: centr(3)
439    REAL(rstd) :: vet(3),vep(3), vertex(3)
440    INTEGER :: ind,i,j,k,n
441    TYPE(t_domain),POINTER :: d
442    REAL(rstd) ::  S12
443    REAL(rstd) :: w(6)
444    REAL(rstd) :: lon,lat
445    INTEGER :: ii_glo,jj_glo
446    REAL(rstd) :: S
447         
448     
449    CALL optimize_geometry
450    CALL remap_schmidt_loc
451    CALL update_circumcenters
452    ! copy position of generators and vertices back into domain(:)%xyz/vertex
453    ! so that XIOS gets the right values
454    CALL update_domain
455
456    DO ind=1,ndomain
457      IF (.NOT. assigned_domain(ind)  .OR. .NOT. is_omp_level_master ) CYCLE
458      d=>domain(ind)
459      CALL swap_dimensions(ind)
460      CALL swap_geometry(ind)
461      lon_i(:)=0 ; lat_i(:)=0
462      lon_e(:)=0 ; lat_e(:)=0
463      DO j=jj_begin-1,jj_end+1
464        DO i=ii_begin-1,ii_end+1
465          n=(j-1)*iim+i
466
467          DO k=0,5
468            ne(n,k+1)=d%ne(k,i,j)
469          ENDDO
470
471          vect(:,1)=xyz_v(n+z_rup,:)
472          vect(:,2)=xyz_v(n+z_up,:)
473          vect(:,3)=xyz_v(n+z_lup,:)
474          vect(:,4)=xyz_v(n+z_ldown,:)
475          vect(:,5)=xyz_v(n+z_down,:)
476          vect(:,6)=xyz_v(n+z_rdown,:)
477          CALL compute_centroid(vect,6,centr)
478          centroid(n,:)=centr(:)
479
480               
481          CALL xyz2lonlat(xyz_v(n+z_up,:),lon,lat)
482          fv(n+z_up)=2*sin(lat)*omega
483          CALL xyz2lonlat(xyz_v(n+z_down,:),lon,lat)
484          fv(n+z_down)=2*sin(lat)*omega
485         
486          bi(n)=0. 
487       
488          CALL dist_cart(xyz_i(n,:),xyz_i(n+t_right,:),de(n+u_right))
489          CALL dist_cart(xyz_i(n,:),xyz_i(n+t_lup,:),de(n+u_lup))
490          CALL dist_cart(xyz_i(n,:),xyz_i(n+t_ldown,:),de(n+u_ldown))
491         
492          CALL div_arc_bis(xyz_i(n,:),xyz_i(n+t_right,:),0.5,xyz_e(n+u_right,:))
493          CALL div_arc_bis(xyz_i(n,:),xyz_i(n+t_lup,:),0.5,xyz_e(n+u_lup,:))
494          CALL div_arc_bis(xyz_i(n,:),xyz_i(n+t_ldown,:),0.5,xyz_e(n+u_ldown,:))
495
496          CALL dist_cart(xyz_v(n+z_rdown,:), xyz_v(n+z_rup,:),le(n+u_right))
497          CALL dist_cart(xyz_v(n+z_up,:), xyz_v(n+z_lup,:),le(n+u_lup))
498          CALL dist_cart(xyz_v(n+z_ldown,:), xyz_v(n+z_down,:),le(n+u_ldown))
499
500          le_de(n+u_right)=le(n+u_right)/de(n+u_right) ! NaN possible but should be harmless
501          le_de(n+u_lup)  =le(n+u_lup)  /de(n+u_lup)
502          le_de(n+u_ldown)=le(n+u_ldown)/de(n+u_ldown)
503
504          Ai(n)=0
505          DO k=0,5
506            CALL surf_triangle(xyz_i(n,:),xyz_i(n+t_pos(k+1),:),xyz_i(n+t_pos(MOD((k+1+6),6)+1),:),surf_v(k+1))
507            CALL surf_triangle(xyz_i(n,:),xyz_v(n+z_pos(MOD((k-1+6),6)+1),:),xyz_v(n+z_pos(k+1),:),surf(k+1))
508            Ai(n)=Ai(n)+surf(k+1)
509            IF (i==ii_end .AND. j==jj_begin) THEN
510              IF (Ai(n)<1e20) THEN
511              ELSE
512                PRINT *,"PB !!",Ai(n),k,surf(k+1)
513                PRINT*,xyz_i(n,:),xyz_v(n+z_pos(MOD((k-1+6),6)+1),:),xyz_v(n+z_pos(k+1),:)
514              ENDIF
515            ENDIF
516          ENDDO
517
518          ! Sign convention : Ringler et al., JCP 2010, eq. 21 p. 3071
519          ! Normal component is along outgoing normal vector if ne=1
520
521          CALL cross_product2(xyz_v(n+z_rdown,:),xyz_v(n+z_rup,:),vep)
522          IF (norm(vep)>1e-30) THEN
523            vep(:)=vep(:)/norm(vep)                         ! Inward normal vector
524            CALL cross_product2(vep,xyz_e(n+u_right,:),vet) ! Counter-clockwise tangent vector
525            vet(:)=vet(:)/norm(vet)
526            ep_e(n+u_right,:)=-vep(:)*ne(n,right)
527            et_e(n+u_right,:)=vet(:)*ne(n,right)
528          ENDIF
529
530          CALL cross_product2(xyz_v(n+z_up,:),xyz_v(n+z_lup,:),vep)
531          IF (norm(vep)>1e-30) THEN
532            vep(:)=vep(:)/norm(vep)
533            CALL cross_product2(vep,xyz_e(n+u_lup,:),vet)
534            vet(:)=vet(:)/norm(vet)
535            ep_e(n+u_lup,:)=-vep(:)*ne(n,lup)
536            et_e(n+u_lup,:)=vet(:)*ne(n,lup)
537          ENDIF
538
539          CALL cross_product2(xyz_v(n+z_ldown,:),xyz_v(n+z_down,:),vep)
540          IF (norm(vep)>1e-30) THEN
541            vep(:)=vep(:)/norm(vep)
542            CALL cross_product2(vep,xyz_e(n+u_ldown,:),vet)
543            vet(:)=vet(:)/norm(vet)
544            ep_e(n+u_ldown,:)=-vep(:)*ne(n,ldown)
545            et_e(n+u_ldown,:)=vet(:)*ne(n,ldown)
546          ENDIF
547
548          CALL xyz2lonlat(xyz_i(n,:),lon,lat)
549          lon_i(n)=lon
550          lat_i(n)=lat
551          elon_i(n,1) = -sin(lon)
552          elon_i(n,2) = cos(lon)
553          elon_i(n,3) = 0
554          elat_i(n,1) = -cos(lon)*sin(lat)
555          elat_i(n,2) = -sin(lon)*sin(lat)
556          elat_i(n,3) = cos(lat)
557
558         
559          CALL xyz2lonlat(xyz_e(n+u_right,:),lon,lat)
560          lon_e(n+u_right)=lon
561          lat_e(n+u_right)=lat
562          elon_e(n+u_right,1) = -sin(lon)
563          elon_e(n+u_right,2) = cos(lon)
564          elon_e(n+u_right,3) = 0
565          elat_e(n+u_right,1) = -cos(lon)*sin(lat)
566          elat_e(n+u_right,2) = -sin(lon)*sin(lat)
567          elat_e(n+u_right,3) = cos(lat)
568         
569          CALL xyz2lonlat(xyz_e(n+u_lup,:),lon,lat)
570          lon_e(n+u_lup)=lon
571          lat_e(n+u_lup)=lat
572          elon_e(n+u_lup,1) = -sin(lon)
573          elon_e(n+u_lup,2) = cos(lon)
574          elon_e(n+u_lup,3) = 0
575          elat_e(n+u_lup,1) = -cos(lon)*sin(lat)
576          elat_e(n+u_lup,2) = -sin(lon)*sin(lat)
577          elat_e(n+u_lup,3) = cos(lat)
578 
579          CALL xyz2lonlat(xyz_e(n+u_ldown,:),lon,lat)
580          lon_e(n+u_ldown)=lon
581          lat_e(n+u_ldown)=lat
582          elon_e(n+u_ldown,1) = -sin(lon)
583          elon_e(n+u_ldown,2) = cos(lon)
584          elon_e(n+u_ldown,3) = 0
585          elat_e(n+u_ldown,1) = -cos(lon)*sin(lat)
586          elat_e(n+u_ldown,2) = -sin(lon)*sin(lat)
587          elat_e(n+u_ldown,3) = cos(lat)
588 
589         
590          DO k=0,5
591            CALL surf_triangle(xyz_i(n,:), xyz_v(n+z_pos(k+1),:), xyz_i(n+t_pos(k+1),:),S1(n,k+1) )
592            CALL surf_triangle(xyz_i(n,:), xyz_v(n+z_pos(k+1),:), xyz_i(n+t_pos(MOD(k+1+6,6)+1),:),S2(n,k+1) )
593            S12 = .5*(S1(n,k+1)+S2(n,k+1))
594            Riv(n,k+1)=S12/Ai(n)
595            Riv2(n,k+1)=S12/surf_v(k+1)
596          ENDDO
597
598          DO k=1,6
599            IF (ABS(surf_v(k))<1e-30) THEN
600              Riv(n,k)=0.
601            ENDIF
602          ENDDO
603         
604          Av(n+z_up)=surf_v(vup)+1e-100
605          Av(n+z_down)=surf_v(vdown)+1e-100
606       
607        ENDDO
608      ENDDO
609     
610      DO j=jj_begin,jj_end
611        DO i=ii_begin,ii_end
612          n=(j-1)*iim+i
613   
614          CALL compute_wee(n,right,w)
615          Wee(n+u_right,:,1)=w(1:5)
616
617          CALL compute_wee(n+t_right,left,w)
618          Wee(n+u_right,:,2)=w(1:5)
619
620
621          CALL compute_wee(n,lup,w)
622          Wee(n+u_lup,:,1)=w(1:5)
623
624          CALL compute_wee(n+t_lup,rdown,w)
625          Wee(n+u_lup,:,2)=w(1:5)
626
627
628          CALL compute_wee(n,ldown,w)
629          Wee(n+u_ldown,:,1)=w(1:5)
630
631          CALL compute_wee(n+t_ldown,rup,w)
632          Wee(n+u_ldown,:,2)=w(1:5)
633
634        ENDDO
635      ENDDO
636     
637      DO j=jj_begin,jj_end
638        DO i=ii_begin,ii_end
639          n=(j-1)*iim+i
640          ii_glo=d%ii_begin_glo-d%ii_begin+i
641          jj_glo=d%jj_begin_glo-d%jj_begin+j
642         
643          IF (ii_glo==1 .AND. jj_glo==1) THEN
644            le(n+u_ldown)=0
645            le_de(n+u_ldown)=0
646            xyz_v(n+z_ldown,:)=xyz_v(n+z_down,:)
647                       
648          ENDIF
649
650          IF (ii_glo==iim_glo .AND. jj_glo==1) THEN
651            le(n+u_right)=0
652            le_de(n+u_right)=0
653            xyz_v(n+z_rdown,:)=xyz_v(n+z_rup,:)
654          ENDIF
655
656          IF (ii_glo==iim_glo .AND. jj_glo==jjm_glo) THEN
657            le(n+u_rup)=0
658            le_de(n+u_rup)=0
659            xyz_v(n+z_rup,:)=xyz_v(n+z_up,:)
660          ENDIF
661
662          IF (ii_glo==1 .AND. jj_glo==jjm_glo) THEN
663            le(n+u_lup)=0
664            le_de(n+u_lup)=0
665            xyz_v(n+z_up,:)=xyz_v(n+z_lup,:)
666          ENDIF
667         
668        ENDDO
669      ENDDO
670
671      DO j=jj_begin-1,jj_end+1
672        DO i=ii_begin-1,ii_end+1
673          n=(j-1)*iim+i
674          xyz_i(n,:)=xyz_i(n,:) * radius
675          xyz_v(n+z_up,:)=xyz_v(n+z_up,:) * radius
676          xyz_v(n+z_down,:)=xyz_v(n+z_down,:) *radius
677          de(n+u_right)=de(n+u_right) * radius
678          de(n+u_lup)=de(n+u_lup)*radius
679          de(n+u_ldown)=de(n+u_ldown)*radius
680          xyz_e(n+u_right,:)=xyz_e(n+u_right,:)*radius
681          xyz_e(n+u_lup,:)=xyz_e(n+u_lup,:)*radius
682          xyz_e(n+u_ldown,:)=xyz_e(n+u_ldown,:)*radius
683          le(n+u_right)=le(n+u_right)*radius
684          le(n+u_lup)=le(n+u_lup)*radius
685          le(n+u_ldown)=le(n+u_ldown)*radius
686          Ai(n)=Ai(n)*radius**2
687          Av(n+z_up)=Av(n+z_up)*radius**2
688          Av(n+z_down)=Av(n+z_down)*radius**2
689        ENDDO
690      ENDDO
691                 
692    ENDDO
693
694    CALL transfert_request(geom%Ai,req_i1)
695    CALL transfert_request(geom%centroid,req_i1)
696
697!    CALL surf_triangle(d%xyz(:,ii_begin,jj_begin),d%xyz(:,ii_begin,jj_end),d%xyz(:,ii_end,jj_begin),S)
698 
699  END SUBROUTINE set_geometry
700 
701  SUBROUTINE compute_wee(n,pos,w)
702  IMPLICIT NONE
703    INTEGER,INTENT(IN) :: n
704    INTEGER,INTENT(IN) :: pos
705    REAL(rstd),INTENT(OUT) ::w(6)
706
707    REAL(rstd) :: ne_(0:5)
708    REAL(rstd) :: Riv_(6)
709    INTEGER    :: k
710   
711   
712    DO k=0,5
713      ne_(k)=ne(n,MOD(pos-1+k+6,6)+1) 
714      Riv_(k+1)=Riv(n,MOD(pos-1+k+6,6)+1)
715    ENDDO
716         
717    w(1)=-ne_(0)*ne_(1)*(Riv_(1)-0.5)
718    w(2)=-ne_(2)*(ne_(0)*Riv_(2)-w(1)*ne_(1))
719    w(3)=-ne_(3)*(ne_(0)*Riv_(3)-w(2)*ne_(2))
720    w(4)=-ne_(4)*(ne_(0)*Riv_(4)-w(3)*ne_(3))
721    w(5)=-ne_(5)*(ne_(0)*Riv_(5)-w(4)*ne_(4))
722    w(6)=ne_(0)*ne_(5)*(Riv_(6)-0.5)
723   
724!    IF ( ABS(w(5)-w(6))>1e-20) PRINT *, "pb pour wee : w(5)!=w(6)",sum(Riv_(:))
725
726   END SUBROUTINE compute_wee
727           
728
729 
730  SUBROUTINE compute_geometry
731  IMPLICIT NONE
732    CALL allocate_geometry
733    CALL set_geometry
734   
735  END SUBROUTINE compute_geometry
736 
737END MODULE geometry
Note: See TracBrowser for help on using the repository browser.