[cig-commits] r18978 - in seismo/3D/SPECFEM3D_GLOBE/trunk: . doc/USER_MANUAL setup src/auxiliaries src/meshfem3D src/shared src/specfem3D

danielpeter at geodynamics.org danielpeter at geodynamics.org
Tue Sep 27 17:05:16 PDT 2011


Author: danielpeter
Date: 2011-09-27 17:05:15 -0700 (Tue, 27 Sep 2011)
New Revision: 18978

Added:
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_element.F90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.F90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.F90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.F90
Removed:
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.f90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.f90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.f90
Modified:
   seismo/3D/SPECFEM3D_GLOBE/trunk/configure
   seismo/3D/SPECFEM3D_GLOBE/trunk/configure.ac
   seismo/3D/SPECFEM3D_GLOBE/trunk/doc/USER_MANUAL/manual_SPECFEM3D_GLOBE.pdf
   seismo/3D/SPECFEM3D_GLOBE/trunk/doc/USER_MANUAL/manual_SPECFEM3D_GLOBE.tex
   seismo/3D/SPECFEM3D_GLOBE/trunk/setup/constants.h.in
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/auxiliaries/combine_vol_data.f90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/meshfem3D/meshfem3D_models.f90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/shared/write_c_binary.c
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/Makefile.in
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/noise_tomography.f90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/read_mesh_databases.f90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/setup_sources_receivers.f90
   seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/write_movie_volume.f90
Log:
optimizes some element calculations and adds pre-processing; additional compiler flag -D_HANDOPT would turn on hand-optimized loops; renames specfem3D.f90 to specfem3D.F90, and so with compute_forces_crust_mantle_Dev.F90 and compute_forces_inner_core_Dev.F90; adds new file compute_element.F90; updates movie volume outputs; sets smaller NSOURCES_SUBSET_MAX in constants.h to avoid memory problems with large simulations

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/configure
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/configure	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/configure	2011-09-28 00:05:15 UTC (rev 18978)
@@ -557,7 +557,7 @@
 PACKAGE_BUGREPORT='jtromp AT princeton.edu'
 PACKAGE_URL=''
 
-ac_unique_file="src/specfem3D/specfem3D.f90"
+ac_unique_file="src/specfem3D/specfem3D.F90"
 # Factoring default headers for most tests.
 ac_includes_default="\
 #include <stdio.h>

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/configure.ac
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/configure.ac	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/configure.ac	2011-09-28 00:05:15 UTC (rev 18978)
@@ -11,7 +11,7 @@
 
 AC_PREREQ(2.61)
 AC_INIT([Specfem3D Globe], [5.1.1], [jtromp AT princeton.edu], [Specfem3DGlobe])
-AC_CONFIG_SRCDIR([src/specfem3D/specfem3D.f90])
+AC_CONFIG_SRCDIR([src/specfem3D/specfem3D.F90])
 AC_CONFIG_HEADER([setup/config.h])
 AC_CONFIG_MACRO_DIR([m4])
 

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/doc/USER_MANUAL/manual_SPECFEM3D_GLOBE.pdf
===================================================================
(Binary files differ)

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/doc/USER_MANUAL/manual_SPECFEM3D_GLOBE.tex
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/doc/USER_MANUAL/manual_SPECFEM3D_GLOBE.tex	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/doc/USER_MANUAL/manual_SPECFEM3D_GLOBE.tex	2011-09-28 00:05:15 UTC (rev 18978)
@@ -339,9 +339,12 @@
 \noindent\texttt{./configure FC=xlf90\_r MPIFC=mpif90 CC=xlc\_r CFLAGS="-O3 -q64" FCFLAGS="-O3 -q64"}.\\
 
 On SGI systems, \texttt{flags.guess} automatically informs \texttt{configure}
-to insert `\texttt{`TRAP\_FPE=OFF}'' into the generated \texttt{Makefile}
+to insert ``\texttt{TRAP\_FPE=OFF}'' into the generated \texttt{Makefile}
 in order to turn underflow trapping off.\\
 
+Some do-loops have been modified using a common technique to help compilers enhance pipelining and make better use
+of the cache. If you want to use these hand-optimized loops, add an additional flag ``\texttt{-D\_HANDOPT}'' to your compiler options.\\
+
 If you run very large meshes on a relatively small number
 of processors, the memory size needed on each processor might become
 greater than 2 gigabytes, which is the upper limit for 32-bit addressing.
@@ -2253,7 +2256,7 @@
 
 To make the code output your favorite ``value'' simply add a new \texttt{\small MOVIE\_VOLUME\_TYPE},
 a new subroutine to \texttt{\small write\_movie\_volume.f90} and a
-subroutine call to \texttt{\small specfem3D.f90}.
+subroutine call to \texttt{\small specfem3D.F90}.
 
 A utility program to combine the files produced by \texttt{\small MOVIE\_VOLUME\_TYPE}
 \texttt{\small =} \texttt{\small 1,2,3} is provided in \texttt{\small combine\_paraview}~\\

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/setup/constants.h.in
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/setup/constants.h.in	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/setup/constants.h.in	2011-09-28 00:05:15 UTC (rev 18978)
@@ -212,7 +212,7 @@
   double precision, parameter :: SOURCE_DECAY_MIMIC_TRIANGLE = 1.628d0
 
 ! maximum number of sources to locate simultaneously
-  integer, parameter :: NSOURCES_SUBSET_MAX = 1000
+  integer, parameter :: NSOURCES_SUBSET_MAX = 100
 
 ! use a force source located exactly at a grid point instead of a CMTSOLUTION source
 ! this can be useful e.g. for asteroid impact simulations

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/auxiliaries/combine_vol_data.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/auxiliaries/combine_vol_data.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/auxiliaries/combine_vol_data.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -269,7 +269,13 @@
       ibool_dat(:) = 0.0
       if( AVERAGE_GLOBALPOINTS ) then
         do ispec=1,nspec(it)
-         if (ir/=3 .or. (ir==3 .and. idoubling_inner_core(ispec) /= IFLAG_IN_FICTITIOUS_CUBE)) then
+          ! checks if element counts
+          if (ir==3 ) then
+            ! inner core
+            ! nothing to do for fictitious elements in central cube
+            if( idoubling_inner_core(ispec) == IFLAG_IN_FICTITIOUS_CUBE) cycle
+          endif
+          ! counts and sums global point data
           do k = 1, NGLLZ, dk
             do j = 1, NGLLY, dj
               do i = 1, NGLLX, di
@@ -282,7 +288,6 @@
               enddo
             enddo
           enddo
-         endif
         enddo
         do iglob=1,nglob(it)
           if( ibool_count(iglob) > 0 ) then
@@ -298,7 +303,14 @@
 
       ! write point file
       do ispec=1,nspec(it)
-       if (ir/=3 .or. (ir==3 .and. idoubling_inner_core(ispec) /= IFLAG_IN_FICTITIOUS_CUBE)) then
+        ! checks if element counts
+        if (ir==3 ) then
+          ! inner core
+          ! nothing to do for fictitious elements in central cube
+          if( idoubling_inner_core(ispec) == IFLAG_IN_FICTITIOUS_CUBE) cycle
+        endif
+       
+        ! writes out global point data
         do k = 1, NGLLZ, dk
           do j = 1, NGLLY, dj
             do i = 1, NGLLX, di
@@ -349,21 +361,52 @@
             enddo ! i
           enddo ! j
         enddo ! k
-       endif ! fictitious elements in central cube
       enddo !ispec
 
       ! no way to check the number of points for low-res
-      if (HIGH_RESOLUTION_MESH .and. numpoin /= npoint(it)) then
-        print*,'region:',ir
-        print*,'error number of points:',numpoin,npoint(it)
-        stop 'different number of points (high-res)'
+      if (HIGH_RESOLUTION_MESH ) then
+        if( ir==3 ) then
+          npoint(it) = numpoin
+        elseif( numpoin /= npoint(it)) then
+          print*,'region:',ir
+          print*,'error number of points:',numpoin,npoint(it)
+          stop 'different number of points (high-res)'
+        endif
       else if (.not. HIGH_RESOLUTION_MESH) then
         npoint(it) = numpoin
       endif
 
       ! write elements file
+      numpoin = 0
       do ispec = 1, nspec(it)
-       if (ir/=3 .or. (ir==3 .and. idoubling_inner_core(ispec) /= IFLAG_IN_FICTITIOUS_CUBE)) then
+        ! checks if element counts
+        if (ir==3 ) then
+          ! inner core          
+          ! fictitious elements in central cube
+          if( idoubling_inner_core(ispec) == IFLAG_IN_FICTITIOUS_CUBE) then
+            ! connectivity must be given, otherwise element count would be wrong
+            ! maps "fictitious" connectivity, element is all with iglob = 1
+            do k = 1, NGLLZ-1, dk
+              do j = 1, NGLLY-1, dj
+                do i = 1, NGLLX-1, di
+                  call write_integer_fd(efd,1)
+                  call write_integer_fd(efd,1)
+                  call write_integer_fd(efd,1)
+                  call write_integer_fd(efd,1)
+                  call write_integer_fd(efd,1)
+                  call write_integer_fd(efd,1)
+                  call write_integer_fd(efd,1)
+                  call write_integer_fd(efd,1)
+                enddo ! i
+              enddo ! j
+            enddo ! k                 
+            ! takes next element
+            cycle
+          endif          
+        endif
+      
+        ! writes out element connectivity
+        numpoin = numpoin + 1 ! counts elements
         do k = 1, NGLLZ-1, dk
           do j = 1, NGLLY-1, dj
             do i = 1, NGLLX-1, di
@@ -393,8 +436,7 @@
               call write_integer_fd(efd,n8)
             enddo ! i
           enddo ! j
-        enddo ! k
-       endif ! fictitious elements in central cube
+        enddo ! k        
       enddo ! ispec
 
       np = np + npoint(it)

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/meshfem3D/meshfem3D_models.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/meshfem3D/meshfem3D_models.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/meshfem3D/meshfem3D_models.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -429,6 +429,9 @@
 
   logical ANISOTROPIC_INNER_CORE
 
+! to create a reference model based on 1D_REF but with 3D crust and 410/660 topography
+  logical,parameter :: USE_1D_REFERENCE = .false.
+  
   end module meshfem3D_models_par
 
 
@@ -895,6 +898,16 @@
                     lmxhpa,itypehpa,ihpakern,numcoe,ivarkern, &
                     nconpt,iver,iconpt,conpt,xlaspl,xlospl,radspl, &
                     coe,vercof,vercofd,ylmcof,wk1,wk2,wk3,kerstr,varstr)
+
+        ! to use speed values from the 1D reference model but with 3D mesh variations
+        if( USE_1D_REFERENCE ) then
+          ! sets all 3D variations in the mantle to zero
+          dvpv = 0.d0
+          dvph = 0.d0
+          dvsv = 0.d0
+          dvsh = 0.d0          
+        endif
+        
         if(TRANSVERSE_ISOTROPY) then
           vpv=vpv*(1.0d0+dble(dvpv))
           vph=vph*(1.0d0+dble(dvph))

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/shared/write_c_binary.c
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/shared/write_c_binary.c	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/shared/write_c_binary.c	2011-09-28 00:05:15 UTC (rev 18978)
@@ -27,6 +27,9 @@
  !=====================================================================
  */
 
+// for large files
+#define _FILE_OFFSET_BITS  64
+
 // after Brian's function
 
 #include "config.h"
@@ -170,7 +173,7 @@
 
 //void
 //FC_FUNC_(open_file_abs_r_fbin,OPEN_FILE_ABS_R_FBIN)(int *fid, char *filename,int *length, int *filesize){
-void open_file_abs_r_fbin(int *fid, char *filename,int *length, int *filesize){
+void open_file_abs_r_fbin(int *fid, char *filename,int *length, long long *filesize){
 
 // opens file for read access
 
@@ -179,7 +182,8 @@
   char * fncopy;
   char * blank;
   FILE *ft;
-
+  int ret;
+  
   // checks filesize
   if( *filesize == 0 ){
     perror("Error file size for reading");
@@ -194,13 +198,17 @@
   }
 
   // opens file
-  ft = fopen( fncopy, "r+" );
+  ft = fopen( fncopy, "rb+" );
   if( ft == NULL ) { perror("fopen"); exit(-1); }
 
   // sets mode for full buffering
   work_buffer[*fid] = (char *)malloc(MAX_B);
-  setvbuf( ft, work_buffer[*fid], _IOFBF, (size_t)MAX_B );
-
+  ret = setvbuf( ft, work_buffer[*fid], _IOFBF, (size_t)MAX_B );
+  if( ret != 0 ){
+    perror("Error setting working buffer");
+    exit(EXIT_FAILURE);  
+  }
+  
   // stores file index id fid: from 0 to 8
   fp_abs[*fid] = ft;
 
@@ -209,7 +217,7 @@
 
 //void
 //FC_FUNC_(open_file_abs_w_fbin,OPEN_FILE_ABS_W_FBIN)(int *fid, char *filename, int *length, int *filesize){
-void open_file_abs_w_fbin(int *fid, char *filename, int *length, int *filesize){
+void open_file_abs_w_fbin(int *fid, char *filename, int *length, long long *filesize){
 
 // opens file for write access
 
@@ -218,10 +226,11 @@
   char * fncopy;
   char * blank;
   FILE *ft;
-
+  int ret;
+  
   // checks filesize
   if( *filesize == 0 ){
-    perror("Error file size for reading");
+    perror("Error file size for writing");
     exit(EXIT_FAILURE);
   }
 
@@ -233,13 +242,17 @@
   }
 
   // opens file
-  ft = fopen( fncopy, "w+" );
+  ft = fopen( fncopy, "wb+" );
   if( ft == NULL ) { perror("fopen"); exit(-1); }
 
   // sets mode for full buffering
   work_buffer[*fid] = (char *)malloc(MAX_B);
-  setvbuf( ft, work_buffer[*fid], _IOFBF, (size_t)MAX_B );
-
+  ret = setvbuf( ft, work_buffer[*fid], _IOFBF, (size_t)MAX_B );
+  if( ret != 0 ){
+    perror("Error setting working buffer");
+    exit(EXIT_FAILURE);  
+  }
+  
   // stores file index id fid: from 0 to 8
   fp_abs[*fid] = ft;
 
@@ -261,7 +274,7 @@
 
 //void
 //FC_FUNC_(write_abs_fbin,WRITE_ABS_FBIN)(int *fid, void *buffer, int *length, int *index){
-void write_abs_fbin(int *fid, void *buffer, int *length, int *index){
+void write_abs_fbin(int *fid, char *buffer, int *length, int *index){
 
 // writes binary file data in chunks of MAX_B
 
@@ -277,10 +290,6 @@
   buf = buffer;
   ret = 0;
 
-  //float dat[2];
-  //memcpy(dat,buffer,*length);
-  //printf("buffer: %f %f\n",dat[0],dat[1]);
-
   // writes items of maximum MAX_B to the file
   while (remlen > 0){
 
@@ -301,21 +310,27 @@
 
 //void
 //FC_FUNC_(read_abs_fbin,READ_ABS_FBIN)(int *fid, void *buffer, int *length, int *index){
-void read_abs_fbin(int *fid, void *buffer, int *length, int *index){
+void read_abs_fbin(int *fid, char *buffer, int *length, int *index){
 
 // reads binary file data in chunks of MAX_B
 
   FILE *ft;
-  int ret,itemlen,remlen,donelen,pos;
+  int ret,itemlen,remlen,donelen;
+  long long pos;
   void *buf;
 
   // file pointer
   ft = fp_abs[*fid];
 
   // positions file pointer (for reverse time access)
-  pos = (*length) * (*index -1 );
-  fseek(ft, pos , SEEK_SET);
+  pos = ((long long)*length) * (*index -1 );
 
+  ret = fseek(ft, pos , SEEK_SET);
+  if ( ret != 0 ) {
+    perror("Error fseek");
+    exit(EXIT_FAILURE);
+  }
+  
   donelen = 0;
   remlen = *length;
   buf = buffer;
@@ -343,9 +358,6 @@
     }
   }
 
-  //float dat[2];
-  //memcpy(dat,buffer,*length);
-  //printf("return buffer: %f %f\n",dat[0],dat[1]);
 }
 
 
@@ -385,11 +397,11 @@
 // file descriptors
 static int map_fd_abs[ABS_FILEID];
 // file sizes
-static int filesize_abs[ABS_FILEID];
+static long long filesize_abs[ABS_FILEID];
 
 //void
 //FC_FUNC_(open_file_abs_w_map,OPEN_FILE_ABS_W_MAP)(int *fid, char *filename, int *length, int *filesize){
-void open_file_abs_w_map(int *fid, char *filename, int *length, int *filesize){
+void open_file_abs_w_map(int *fid, char *filename, int *length, long long *filesize){
 
 // opens file for write access
 
@@ -429,14 +441,13 @@
 
   free(fncopy);
 
-
   /* Stretch the file size to the size of the (mmapped) array of ints
    */
   filesize_abs[*fid] = *filesize;
   result = lseek(ft, filesize_abs[*fid] - 1, SEEK_SET);
   if (result == -1) {
     close(ft);
-    perror("Error calling fseek() to 'stretch' the file");
+    perror("Error calling lseek() to 'stretch' the file");
     exit(EXIT_FAILURE);
   }
 
@@ -477,7 +488,7 @@
 
 //void
 //FC_FUNC_(open_file_abs_r_map,OPEN_FILE_ABS_R_MAP)(int *fid, char *filename,int *length, int *filesize){
-void open_file_abs_r_map(int *fid, char *filename,int *length, int *filesize){
+void open_file_abs_r_map(int *fid, char *filename,int *length, long long *filesize){
 
   // opens file for read access
   char * fncopy;
@@ -549,12 +560,12 @@
 void write_abs_map(int *fid, char *buffer, int *length , int *index){
 
   char *map;
-  int offset;
+  long long offset;
 
   map = map_abs[*fid];
 
   // offset in bytes
-  offset =  (*index -1 ) * (*length) ;
+  offset =  ((long long)*index -1 ) * (*length) ;
 
   // copies buffer to map
   memcpy( &map[offset], buffer ,*length );
@@ -566,12 +577,12 @@
 void read_abs_map(int *fid, char *buffer, int *length , int *index){
 
   char *map;
-  int offset;
+  long long offset;
 
   map = map_abs[*fid];
 
   // offset in bytes
-  offset =  (*index -1 ) * (*length) ;
+  offset =  ((long long)*index -1 ) * (*length) ;
 
   // copies map to buffer
   memcpy( buffer, &map[offset], *length );
@@ -597,7 +608,7 @@
 */
 
 void
-FC_FUNC_(open_file_abs_w,OPEN_FILE_ABS_W)(int *fid, char *filename,int *length, int *filesize) {
+FC_FUNC_(open_file_abs_w,OPEN_FILE_ABS_W)(int *fid, char *filename,int *length, long long *filesize) {
 
 #ifdef   USE_MAP_FUNCTION
   open_file_abs_w_map(fid,filename,length,filesize);
@@ -608,7 +619,7 @@
 }
 
 void
-FC_FUNC_(open_file_abs_r,OPEN_FILE_ABS_R)(int *fid, char *filename,int *length, int *filesize) {
+FC_FUNC_(open_file_abs_r,OPEN_FILE_ABS_R)(int *fid, char *filename,int *length, long long *filesize) {
 
 #ifdef   USE_MAP_FUNCTION
   open_file_abs_r_map(fid,filename,length,filesize);

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/Makefile.in
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/Makefile.in	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/Makefile.in	2011-09-28 00:05:15 UTC (rev 18978)
@@ -128,6 +128,7 @@
 	$O/compute_add_sources.o \
 	$O/compute_boundary_kernel.o \
 	$O/compute_coupling.o \
+	$O/compute_element.o \
 	$O/compute_forces_crust_mantle.o \
 	$O/compute_forces_crust_mantle_Dev.o \
 	$O/compute_forces_inner_core.o \
@@ -324,11 +325,14 @@
 $O/compute_coupling.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_coupling.f90
 	${FCCOMPILE_NO_CHECK} -c -o $O/compute_coupling.o ${FCFLAGS_f90} $S/compute_coupling.f90
 
+$O/compute_element.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_element.F90
+	${FCCOMPILE_NO_CHECK} -c -o $O/compute_element.o ${FCFLAGS_f90} $S/compute_element.F90
+
 $O/compute_forces_crust_mantle.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_forces_crust_mantle.f90
 	${FCCOMPILE_NO_CHECK} -c -o $O/compute_forces_crust_mantle.o ${FCFLAGS_f90} $S/compute_forces_crust_mantle.f90
 
-$O/compute_forces_crust_mantle_Dev.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_forces_crust_mantle_Dev.f90
-	${FCCOMPILE_NO_CHECK} -c -o $O/compute_forces_crust_mantle_Dev.o ${FCFLAGS_f90} $S/compute_forces_crust_mantle_Dev.f90
+$O/compute_forces_crust_mantle_Dev.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_forces_crust_mantle_Dev.F90
+	${FCCOMPILE_NO_CHECK} -c -o $O/compute_forces_crust_mantle_Dev.o ${FCFLAGS_f90} $S/compute_forces_crust_mantle_Dev.F90
 
 $O/compute_forces_outer_core.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_forces_outer_core.f90
 	${FCCOMPILE_NO_CHECK} -c -o $O/compute_forces_outer_core.o ${FCFLAGS_f90} $S/compute_forces_outer_core.f90
@@ -339,8 +343,8 @@
 $O/compute_forces_inner_core.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_forces_inner_core.f90
 	${FCCOMPILE_NO_CHECK} -c -o $O/compute_forces_inner_core.o ${FCFLAGS_f90} $S/compute_forces_inner_core.f90
 
-$O/compute_forces_inner_core_Dev.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_forces_inner_core_Dev.f90
-	${FCCOMPILE_NO_CHECK} -c -o $O/compute_forces_inner_core_Dev.o ${FCFLAGS_f90} $S/compute_forces_inner_core_Dev.f90
+$O/compute_forces_inner_core_Dev.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_forces_inner_core_Dev.F90
+	${FCCOMPILE_NO_CHECK} -c -o $O/compute_forces_inner_core_Dev.o ${FCFLAGS_f90} $S/compute_forces_inner_core_Dev.F90
 
 $O/compute_kernels.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/compute_kernels.f90
 	${FCCOMPILE_NO_CHECK} -c -o $O/compute_kernels.o ${FCFLAGS_f90} $S/compute_kernels.f90
@@ -435,8 +439,8 @@
 $O/setup_sources_receivers.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/setup_sources_receivers.f90
 	${MPIFCCOMPILE_NO_CHECK} -c -o $O/setup_sources_receivers.o ${FCFLAGS_f90} $S/setup_sources_receivers.f90
 
-$O/specfem3D.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/specfem3D.f90
-	${MPIFCCOMPILE_NO_CHECK} -c -o $O/specfem3D.o ${FCFLAGS_f90} $S/specfem3D.f90
+$O/specfem3D.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/specfem3D.F90
+	${MPIFCCOMPILE_NO_CHECK} -c -o $O/specfem3D.o ${FCFLAGS_f90} $S/specfem3D.F90
 
 $O/write_movie_surface.o: ${SETUP}/constants.h ${OUTPUT}/values_from_mesher.h $S/write_movie_surface.f90
 	${MPIFCCOMPILE_NO_CHECK} -c -o $O/write_movie_surface.o ${FCFLAGS_f90} $S/write_movie_surface.f90

Added: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_element.F90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_element.F90	                        (rev 0)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_element.F90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -0,0 +1,1570 @@
+!=====================================================================
+!
+!          S p e c f e m 3 D  G l o b e  V e r s i o n  5 . 1
+!          --------------------------------------------------
+!
+!          Main authors: Dimitri Komatitsch and Jeroen Tromp
+!                        Princeton University, USA
+!             and University of Pau / CNRS / INRIA, France
+! (c) Princeton University / California Institute of Technology and University of Pau / CNRS / INRIA
+!                            April 2011
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or
+! (at your option) any later version.
+!
+! This program is distributed in the hope that it will be useful,
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+! GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along
+! with this program; if not, write to the Free Software Foundation, Inc.,
+! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+!
+!=====================================================================
+
+! preprocessing definition: #define _HANDOPT :  turns hand-optimized code on
+!                                         #undef _HANDOPT :  turns hand-optimized code off
+! or compile with: -D_HANDOPT
+!#define _HANDOPT
+ 
+! note: these hand optimizations should help compilers to pipeline the code and make better use of the cache;
+!          depending on compilers, it can further decrease the computation time by ~ 30%.
+!          the original routines are commented with "! way 1", the hand-optimized routines with  "! way 2"
+
+  subroutine compute_element_iso(ispec, &
+                    minus_gravity_table,density_table,minus_deriv_gravity_table, &
+                    xstore,ystore,zstore, &          
+                    xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+                    wgll_cube, &
+                    kappavstore,muvstore, &
+                    ibool, &
+                    R_memory,epsilon_trace_over_3, &
+                    one_minus_sum_beta,vx,vy,vz,vnspec, &          
+                    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3, &
+                    dummyx_loc,dummyy_loc,dummyz_loc,epsilondev_loc,rho_s_H)
+
+! this routine is optimized for NGLLX = NGLLY = NGLLZ = 5 using the Deville et al. (2002) inlined matrix-matrix products
+
+  implicit none
+
+  include "constants.h"
+
+  ! include values created by the mesher
+  ! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! element id
+  integer :: ispec
+
+  ! arrays with mesh parameters per slice
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool
+
+  ! x y and z contain r theta and phi
+  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: xstore,ystore,zstore
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: &
+        xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz
+
+  ! array with derivatives of Lagrange polynomials and precalculated products
+  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
+
+  ! store anisotropic properties only where needed to save memory
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ISO_MANTLE) :: &
+        kappavstore,muvstore
+
+
+  ! attenuation
+  ! memory variables for attenuation
+  ! memory variables R_ij are stored at the local rather than global level
+  ! to allow for optimization of cache access by compiler
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory
+  real(kind=CUSTOM_REAL),dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilon_trace_over_3
+
+  integer :: vx,vy,vz,vnspec
+  real(kind=CUSTOM_REAL), dimension(vx, vy, vz, vnspec) :: one_minus_sum_beta
+
+  ! gravity
+  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table,density_table,minus_deriv_gravity_table
+
+  ! element info
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: &
+    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: dummyx_loc,dummyy_loc,dummyz_loc
+  
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: rho_s_H
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
+
+! local parameters
+  real(kind=CUSTOM_REAL) one_minus_sum_beta_use
+  real(kind=CUSTOM_REAL) xixl,xiyl,xizl,etaxl,etayl,etazl,gammaxl,gammayl,gammazl,jacobianl
+  real(kind=CUSTOM_REAL) duxdxl,duxdyl,duxdzl,duydxl,duydyl,duydzl,duzdxl,duzdyl,duzdzl
+  real(kind=CUSTOM_REAL) duxdxl_plus_duydyl,duxdxl_plus_duzdzl,duydyl_plus_duzdzl
+  real(kind=CUSTOM_REAL) duxdyl_plus_duydxl,duzdxl_plus_duxdzl,duzdyl_plus_duydzl
+  real(kind=CUSTOM_REAL) sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz
+  real(kind=CUSTOM_REAL) sigma_yx,sigma_zx,sigma_zy
+
+  real(kind=CUSTOM_REAL) templ
+  real(kind=CUSTOM_REAL) lambdal,mul,lambdalplus2mul
+  real(kind=CUSTOM_REAL) kappal
+
+  ! for gravity
+  double precision dphi,dtheta
+  double precision radius,rho,minus_g,minus_dg
+  double precision minus_g_over_radius,minus_dg_plus_g_over_radius
+  double precision cos_theta,sin_theta,cos_phi,sin_phi
+  double precision cos_theta_sq,sin_theta_sq,cos_phi_sq,sin_phi_sq
+  double precision factor,sx_l,sy_l,sz_l,gxl,gyl,gzl
+  double precision Hxxl,Hyyl,Hzzl,Hxyl,Hxzl,Hyzl
+
+  integer :: ispec_strain
+  integer :: i,j,k
+  integer :: int_radius 
+  integer :: iglob1 
+  
+  ! isotropic element
+  
+  do k=1,NGLLZ
+    do j=1,NGLLY
+      do i=1,NGLLX
+        ! get derivatives of ux, uy and uz with respect to x, y and z
+        xixl = xix(i,j,k,ispec)
+        xiyl = xiy(i,j,k,ispec)
+        xizl = xiz(i,j,k,ispec)
+        etaxl = etax(i,j,k,ispec)
+        etayl = etay(i,j,k,ispec)
+        etazl = etaz(i,j,k,ispec)
+        gammaxl = gammax(i,j,k,ispec)
+        gammayl = gammay(i,j,k,ispec)
+        gammazl = gammaz(i,j,k,ispec)
+
+        ! compute the jacobian
+        jacobianl = 1._CUSTOM_REAL / (xixl*(etayl*gammazl-etazl*gammayl) &
+                      - xiyl*(etaxl*gammazl-etazl*gammaxl) &
+                      + xizl*(etaxl*gammayl-etayl*gammaxl))
+
+        duxdxl = xixl*tempx1(i,j,k) + etaxl*tempx2(i,j,k) + gammaxl*tempx3(i,j,k)
+        duxdyl = xiyl*tempx1(i,j,k) + etayl*tempx2(i,j,k) + gammayl*tempx3(i,j,k)
+        duxdzl = xizl*tempx1(i,j,k) + etazl*tempx2(i,j,k) + gammazl*tempx3(i,j,k)
+
+        duydxl = xixl*tempy1(i,j,k) + etaxl*tempy2(i,j,k) + gammaxl*tempy3(i,j,k)
+        duydyl = xiyl*tempy1(i,j,k) + etayl*tempy2(i,j,k) + gammayl*tempy3(i,j,k)
+        duydzl = xizl*tempy1(i,j,k) + etazl*tempy2(i,j,k) + gammazl*tempy3(i,j,k)
+
+        duzdxl = xixl*tempz1(i,j,k) + etaxl*tempz2(i,j,k) + gammaxl*tempz3(i,j,k)
+        duzdyl = xiyl*tempz1(i,j,k) + etayl*tempz2(i,j,k) + gammayl*tempz3(i,j,k)
+        duzdzl = xizl*tempz1(i,j,k) + etazl*tempz2(i,j,k) + gammazl*tempz3(i,j,k)
+
+        ! precompute some sums to save CPU time
+        duxdxl_plus_duydyl = duxdxl + duydyl
+        duxdxl_plus_duzdzl = duxdxl + duzdzl
+        duydyl_plus_duzdzl = duydyl + duzdzl
+        duxdyl_plus_duydxl = duxdyl + duydxl
+        duzdxl_plus_duxdzl = duzdxl + duxdzl
+        duzdyl_plus_duydzl = duzdyl + duydzl
+
+        ! compute deviatoric strain
+        if (COMPUTE_AND_STORE_STRAIN) then
+          if(NSPEC_CRUST_MANTLE_STRAIN_ONLY == 1) then
+            ispec_strain = 1
+          else
+            ispec_strain = ispec
+          endif
+          templ = ONE_THIRD * (duxdxl + duydyl + duzdzl)
+          epsilon_trace_over_3(i,j,k,ispec_strain) = templ
+          epsilondev_loc(1,i,j,k) = duxdxl - templ
+          epsilondev_loc(2,i,j,k) = duydyl - templ
+          epsilondev_loc(3,i,j,k) = 0.5 * duxdyl_plus_duydxl
+          epsilondev_loc(4,i,j,k) = 0.5 * duzdxl_plus_duxdzl
+          epsilondev_loc(5,i,j,k) = 0.5 * duzdyl_plus_duydzl
+        endif
+
+       ! precompute terms for attenuation if needed
+        if(ATTENUATION_VAL) then
+          one_minus_sum_beta_use = one_minus_sum_beta(i,j,k,ispec)
+        endif
+
+        !
+        ! compute  isotropic  elements
+        !
+
+        ! layer with no transverse isotropy, use kappav and muv
+        kappal = kappavstore(i,j,k,ispec)
+        mul = muvstore(i,j,k,ispec)
+
+        ! use unrelaxed parameters if attenuation
+        if(ATTENUATION_VAL) mul = mul * one_minus_sum_beta_use
+
+        lambdalplus2mul = kappal + FOUR_THIRDS * mul
+        lambdal = lambdalplus2mul - 2.0*mul
+
+        ! compute stress sigma
+        sigma_xx = lambdalplus2mul*duxdxl + lambdal*duydyl_plus_duzdzl
+        sigma_yy = lambdalplus2mul*duydyl + lambdal*duxdxl_plus_duzdzl
+        sigma_zz = lambdalplus2mul*duzdzl + lambdal*duxdxl_plus_duydyl
+
+        sigma_xy = mul*duxdyl_plus_duydxl
+        sigma_xz = mul*duzdxl_plus_duxdzl
+        sigma_yz = mul*duzdyl_plus_duydzl
+
+        ! subtract memory variables if attenuation
+        if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. )  ) then
+
+          ! note: fortran passes pointers to array location, thus R_memory(1,1,...) should be fine
+          call compute_element_att_stress( R_memory(1,1,i,j,k,ispec), &
+                    sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz)
+
+        endif ! ATTENUATION_VAL
+
+        ! define symmetric components of sigma for gravity
+        sigma_yx = sigma_xy
+        sigma_zx = sigma_xz
+        sigma_zy = sigma_yz
+
+        ! compute non-symmetric terms for gravity
+        if(GRAVITY_VAL) then
+
+            ! use mesh coordinates to get theta and phi
+            ! x y and z contain r theta and phi
+            iglob1 = ibool(i,j,k,ispec)
+
+            dtheta = dble(ystore(iglob1))
+            dphi = dble(zstore(iglob1))
+
+            cos_theta = dcos(dtheta)
+            sin_theta = dsin(dtheta)
+            cos_phi = dcos(dphi)
+            sin_phi = dsin(dphi)
+
+            cos_theta_sq = cos_theta*cos_theta
+            sin_theta_sq = sin_theta*sin_theta
+            cos_phi_sq = cos_phi*cos_phi
+            sin_phi_sq = sin_phi*sin_phi
+
+            ! get g, rho and dg/dr=dg
+            ! spherical components of the gravitational acceleration
+            ! for efficiency replace with lookup table every 100 m in radial direction
+            radius = dble(xstore(iglob1))
+
+            int_radius = nint(10.d0 * radius * R_EARTH_KM )
+            minus_g = minus_gravity_table(int_radius)
+            minus_dg = minus_deriv_gravity_table(int_radius)
+            rho = density_table(int_radius)
+
+            ! Cartesian components of the gravitational acceleration
+            gxl = minus_g*sin_theta*cos_phi
+            gyl = minus_g*sin_theta*sin_phi
+            gzl = minus_g*cos_theta
+
+            ! Cartesian components of gradient of gravitational acceleration
+            ! obtained from spherical components
+            minus_g_over_radius = minus_g / radius            
+            minus_dg_plus_g_over_radius = minus_dg - minus_g_over_radius
+
+            Hxxl = minus_g_over_radius*(cos_phi_sq*cos_theta_sq + sin_phi_sq) + cos_phi_sq*minus_dg*sin_theta_sq
+            Hyyl = minus_g_over_radius*(cos_phi_sq + cos_theta_sq*sin_phi_sq) + minus_dg*sin_phi_sq*sin_theta_sq
+            Hzzl = cos_theta_sq*minus_dg + minus_g_over_radius*sin_theta_sq
+            Hxyl = cos_phi*minus_dg_plus_g_over_radius*sin_phi*sin_theta_sq
+            Hxzl = cos_phi*cos_theta*minus_dg_plus_g_over_radius*sin_theta
+            Hyzl = cos_theta*minus_dg_plus_g_over_radius*sin_phi*sin_theta
+
+            ! distinguish between single and double precision for reals
+            if(CUSTOM_REAL == SIZE_REAL) then
+
+              ! get displacement and multiply by density to compute G tensor
+              sx_l = rho * dble(dummyx_loc(i,j,k)) ! dble(displ_crust_mantle(1,iglob1))
+              sy_l = rho * dble(dummyy_loc(i,j,k)) ! dble(displ_crust_mantle(2,iglob1))
+              sz_l = rho * dble(dummyz_loc(i,j,k)) ! dble(displ_crust_mantle(3,iglob1))
+
+              ! compute G tensor from s . g and add to sigma (not symmetric)
+              sigma_xx = sigma_xx + sngl(sy_l*gyl + sz_l*gzl)
+              sigma_yy = sigma_yy + sngl(sx_l*gxl + sz_l*gzl)
+              sigma_zz = sigma_zz + sngl(sx_l*gxl + sy_l*gyl)
+
+              sigma_xy = sigma_xy - sngl(sx_l * gyl)
+              sigma_yx = sigma_yx - sngl(sy_l * gxl)
+
+              sigma_xz = sigma_xz - sngl(sx_l * gzl)
+              sigma_zx = sigma_zx - sngl(sz_l * gxl)
+
+              sigma_yz = sigma_yz - sngl(sy_l * gzl)
+              sigma_zy = sigma_zy - sngl(sz_l * gyl)
+
+              ! precompute vector
+              factor = dble(jacobianl) * wgll_cube(i,j,k)
+              rho_s_H(1,i,j,k) = sngl(factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl))
+              rho_s_H(2,i,j,k) = sngl(factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl))
+              rho_s_H(3,i,j,k) = sngl(factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl))
+
+            else
+
+              ! get displacement and multiply by density to compute G tensor
+              sx_l = rho * dummyx_loc(i,j,k) ! displ_crust_mantle(1,iglob1)
+              sy_l = rho * dummyy_loc(i,j,k) ! displ_crust_mantle(2,iglob1)
+              sz_l = rho * dummyz_loc(i,j,k) ! displ_crust_mantle(3,iglob1)
+
+              ! compute G tensor from s . g and add to sigma (not symmetric)
+              sigma_xx = sigma_xx + sy_l*gyl + sz_l*gzl
+              sigma_yy = sigma_yy + sx_l*gxl + sz_l*gzl
+              sigma_zz = sigma_zz + sx_l*gxl + sy_l*gyl
+
+              sigma_xy = sigma_xy - sx_l * gyl
+              sigma_yx = sigma_yx - sy_l * gxl
+
+              sigma_xz = sigma_xz - sx_l * gzl
+              sigma_zx = sigma_zx - sz_l * gxl
+
+              sigma_yz = sigma_yz - sy_l * gzl
+              sigma_zy = sigma_zy - sz_l * gyl
+
+              ! precompute vector
+              factor = jacobianl * wgll_cube(i,j,k)
+              rho_s_H(1,i,j,k) = factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl)
+              rho_s_H(2,i,j,k) = factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl)
+              rho_s_H(3,i,j,k) = factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl)
+
+            endif
+
+        endif  ! end of section with gravity terms
+
+        ! form dot product with test vector, non-symmetric form
+        tempx1(i,j,k) = jacobianl * (sigma_xx*xixl + sigma_yx*xiyl + sigma_zx*xizl) 
+        tempy1(i,j,k) = jacobianl * (sigma_xy*xixl + sigma_yy*xiyl + sigma_zy*xizl) 
+        tempz1(i,j,k) = jacobianl * (sigma_xz*xixl + sigma_yz*xiyl + sigma_zz*xizl) 
+
+        tempx2(i,j,k) = jacobianl * (sigma_xx*etaxl + sigma_yx*etayl + sigma_zx*etazl)
+        tempy2(i,j,k) = jacobianl * (sigma_xy*etaxl + sigma_yy*etayl + sigma_zy*etazl)
+        tempz2(i,j,k) = jacobianl * (sigma_xz*etaxl + sigma_yz*etayl + sigma_zz*etazl)
+
+        tempx3(i,j,k) = jacobianl * (sigma_xx*gammaxl + sigma_yx*gammayl + sigma_zx*gammazl)
+        tempy3(i,j,k) = jacobianl * (sigma_xy*gammaxl + sigma_yy*gammayl + sigma_zy*gammazl)
+        tempz3(i,j,k) = jacobianl * (sigma_xz*gammaxl + sigma_yz*gammayl + sigma_zz*gammazl)
+
+      enddo ! NGLLX
+    enddo ! NGLLY
+  enddo ! NGLLZ
+
+  end subroutine compute_element_iso
+
+
+
+!
+!--------------------------------------------------------------------------------------------------
+!
+  
+  
+  
+  
+  subroutine compute_element_tiso(ispec, &
+                    minus_gravity_table,density_table,minus_deriv_gravity_table, &
+                    xstore,ystore,zstore, &
+                    xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+                    wgll_cube, &
+                    kappavstore,kappahstore,muvstore,muhstore,eta_anisostore, &
+                    ibool, &
+                    R_memory,epsilon_trace_over_3, &
+                    one_minus_sum_beta,vx,vy,vz,vnspec, &
+                    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3, &
+                    dummyx_loc,dummyy_loc,dummyz_loc,epsilondev_loc,rho_s_H)
+
+! this routine is optimized for NGLLX = NGLLY = NGLLZ = 5 using the Deville et al. (2002) inlined matrix-matrix products
+
+  implicit none
+
+  include "constants.h"
+
+  ! include values created by the mesher
+  ! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! element id
+  integer :: ispec
+
+  ! arrays with mesh parameters per slice
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool
+
+  ! x y and z contain r theta and phi
+  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: xstore,ystore,zstore
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: &
+        xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz
+
+  ! array with derivatives of Lagrange polynomials and precalculated products
+  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
+
+  ! store anisotropic properties only where needed to save memory
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_TISO_MANTLE) :: &
+        kappahstore,muhstore,eta_anisostore
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ISO_MANTLE) :: &
+        kappavstore,muvstore
+
+
+  ! attenuation
+  ! memory variables for attenuation
+  ! memory variables R_ij are stored at the local rather than global level
+  ! to allow for optimization of cache access by compiler
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory
+  real(kind=CUSTOM_REAL),dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilon_trace_over_3
+
+  integer vx,vy,vz,vnspec
+
+  ! [alpha,beta,gamma]val reduced to N_SLS  to N_SLS*NUM_NODES
+  real(kind=CUSTOM_REAL), dimension(vx, vy, vz, vnspec) :: one_minus_sum_beta
+
+
+  ! gravity
+  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table,density_table,minus_deriv_gravity_table
+
+  ! element info
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: &
+    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: dummyx_loc,dummyy_loc,dummyz_loc
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: rho_s_H
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
+
+
+! local parameters
+  real(kind=CUSTOM_REAL) one_minus_sum_beta_use
+  ! the 21 coefficients for an anisotropic medium in reduced notation
+  real(kind=CUSTOM_REAL) c11,c22,c33,c44,c55,c66,c12,c13,c23,c14,c24,c34,c15,c25,c35,c45,c16,c26,c36,c46,c56
+
+  real(kind=CUSTOM_REAL) rhovphsq,sinphifour,cosphisq,sinphisq,costhetasq,rhovsvsq,sinthetasq, &
+        cosphifour,costhetafour,rhovpvsq,sinthetafour,rhovshsq,cosfourphi, &
+        costwotheta,cosfourtheta,sintwophisq,costheta,sinphi,sintheta,cosphi, &
+        sintwotheta,costwophi,sintwophi,costwothetasq,costwophisq,phi,theta
+
+  real(kind=CUSTOM_REAL) two_rhovsvsq,two_rhovshsq ! two_rhovpvsq,two_rhovphsq
+  real(kind=CUSTOM_REAL) four_rhovsvsq,four_rhovshsq ! four_rhovpvsq,four_rhovphsq
+
+  real(kind=CUSTOM_REAL) twoetaminone,etaminone,eta_aniso
+  real(kind=CUSTOM_REAL) two_eta_aniso,four_eta_aniso,six_eta_aniso
+  real(kind=CUSTOM_REAL) xixl,xiyl,xizl,etaxl,etayl,etazl,gammaxl,gammayl,gammazl,jacobianl
+  real(kind=CUSTOM_REAL) duxdxl,duxdyl,duxdzl,duydxl,duydyl,duydzl,duzdxl,duzdyl,duzdzl
+  real(kind=CUSTOM_REAL) duxdxl_plus_duydyl,duxdxl_plus_duzdzl,duydyl_plus_duzdzl
+  real(kind=CUSTOM_REAL) duxdyl_plus_duydxl,duzdxl_plus_duxdzl,duzdyl_plus_duydzl
+  real(kind=CUSTOM_REAL) sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz
+
+  real(kind=CUSTOM_REAL) templ
+  real(kind=CUSTOM_REAL) templ1,templ1_cos,templ2,templ2_cos,templ3,templ3_two,templ3_cos
+  real(kind=CUSTOM_REAL) kappavl,kappahl,muvl,muhl
+
+  ! for gravity
+  double precision dphi,dtheta
+  double precision radius,rho,minus_g,minus_dg
+  double precision minus_g_over_radius,minus_dg_plus_g_over_radius
+  double precision cos_theta,sin_theta,cos_phi,sin_phi
+  double precision cos_theta_sq,sin_theta_sq,cos_phi_sq,sin_phi_sq
+  double precision factor,sx_l,sy_l,sz_l,gxl,gyl,gzl
+  double precision Hxxl,Hyyl,Hzzl,Hxyl,Hxzl,Hyzl
+  real(kind=CUSTOM_REAL) sigma_yx,sigma_zx,sigma_zy
+
+  integer :: ispec_strain
+  integer :: i,j,k
+  integer :: int_radius
+  integer :: iglob1
+
+  ! transverse isotropic element
+  
+  do k=1,NGLLZ
+    do j=1,NGLLY
+      do i=1,NGLLX
+        ! get derivatives of ux, uy and uz with respect to x, y and z
+        xixl = xix(i,j,k,ispec)
+        xiyl = xiy(i,j,k,ispec)
+        xizl = xiz(i,j,k,ispec)
+        etaxl = etax(i,j,k,ispec)
+        etayl = etay(i,j,k,ispec)
+        etazl = etaz(i,j,k,ispec)
+        gammaxl = gammax(i,j,k,ispec)
+        gammayl = gammay(i,j,k,ispec)
+        gammazl = gammaz(i,j,k,ispec)
+
+        ! compute the jacobian
+        jacobianl = 1._CUSTOM_REAL / (xixl*(etayl*gammazl-etazl*gammayl) &
+                      - xiyl*(etaxl*gammazl-etazl*gammaxl) &
+                      + xizl*(etaxl*gammayl-etayl*gammaxl))
+
+        duxdxl = xixl*tempx1(i,j,k) + etaxl*tempx2(i,j,k) + gammaxl*tempx3(i,j,k)
+        duxdyl = xiyl*tempx1(i,j,k) + etayl*tempx2(i,j,k) + gammayl*tempx3(i,j,k)
+        duxdzl = xizl*tempx1(i,j,k) + etazl*tempx2(i,j,k) + gammazl*tempx3(i,j,k)
+
+        duydxl = xixl*tempy1(i,j,k) + etaxl*tempy2(i,j,k) + gammaxl*tempy3(i,j,k)
+        duydyl = xiyl*tempy1(i,j,k) + etayl*tempy2(i,j,k) + gammayl*tempy3(i,j,k)
+        duydzl = xizl*tempy1(i,j,k) + etazl*tempy2(i,j,k) + gammazl*tempy3(i,j,k)
+
+        duzdxl = xixl*tempz1(i,j,k) + etaxl*tempz2(i,j,k) + gammaxl*tempz3(i,j,k)
+        duzdyl = xiyl*tempz1(i,j,k) + etayl*tempz2(i,j,k) + gammayl*tempz3(i,j,k)
+        duzdzl = xizl*tempz1(i,j,k) + etazl*tempz2(i,j,k) + gammazl*tempz3(i,j,k)
+
+        ! precompute some sums to save CPU time
+        duxdxl_plus_duydyl = duxdxl + duydyl
+        duxdxl_plus_duzdzl = duxdxl + duzdzl
+        duydyl_plus_duzdzl = duydyl + duzdzl
+        duxdyl_plus_duydxl = duxdyl + duydxl
+        duzdxl_plus_duxdzl = duzdxl + duxdzl
+        duzdyl_plus_duydzl = duzdyl + duydzl
+
+        ! compute deviatoric strain
+        if (COMPUTE_AND_STORE_STRAIN) then
+          if(NSPEC_CRUST_MANTLE_STRAIN_ONLY == 1) then
+            ispec_strain = 1
+          else
+            ispec_strain = ispec
+          endif
+          templ = ONE_THIRD * (duxdxl + duydyl + duzdzl)
+          epsilon_trace_over_3(i,j,k,ispec_strain) = templ
+          epsilondev_loc(1,i,j,k) = duxdxl - templ
+          epsilondev_loc(2,i,j,k) = duydyl - templ
+          epsilondev_loc(3,i,j,k) = 0.5 * duxdyl_plus_duydxl
+          epsilondev_loc(4,i,j,k) = 0.5 * duzdxl_plus_duxdzl
+          epsilondev_loc(5,i,j,k) = 0.5 * duzdyl_plus_duydzl
+        endif
+
+        ! precompute terms for attenuation if needed
+        if(ATTENUATION_VAL) then
+          one_minus_sum_beta_use = one_minus_sum_beta(i,j,k,ispec)
+        endif
+
+        !
+        ! compute either isotropic or anisotropic elements
+        !
+
+! note : mesh is built such that anisotropic elements are created first in anisotropic layers,
+!           thus they are listed first ( see in create_regions_mesh.f90: perm_layer() ordering )
+!           this is therefore still in bounds of 1:NSPECMAX_TISO_MANTLE even if NSPECMAX_TISO is less than NSPEC
+
+        ! uncomment to debug
+        !if ( ispec > NSPECMAX_TISO_MANTLE ) then
+        !  print*,'error tiso: ispec = ',ispec,'max = ',NSPECMAX_TISO_MANTLE
+        !  call exit_mpi(0,'error tiso ispec bounds')
+        !endif
+
+        ! use Kappa and mu from transversely isotropic model
+        kappavl = kappavstore(i,j,k,ispec)
+        muvl = muvstore(i,j,k,ispec)
+
+        kappahl = kappahstore(i,j,k,ispec)
+        muhl = muhstore(i,j,k,ispec)
+
+        ! use unrelaxed parameters if attenuation
+        ! eta does not need to be shifted since it is a ratio
+        if(ATTENUATION_VAL) then
+          muvl = muvl * one_minus_sum_beta_use
+          muhl = muhl * one_minus_sum_beta_use
+        endif
+
+        rhovpvsq = kappavl + FOUR_THIRDS * muvl  !!! that is C
+        rhovphsq = kappahl + FOUR_THIRDS * muhl  !!! that is A
+
+        rhovsvsq = muvl  !!! that is L
+        rhovshsq = muhl  !!! that is N
+
+        eta_aniso = eta_anisostore(i,j,k,ispec)  !!! that is  F / (A - 2 L)
+
+        ! use mesh coordinates to get theta and phi
+        ! ystore and zstore contain theta and phi
+        iglob1 = ibool(i,j,k,ispec)
+        
+        theta = ystore(iglob1)
+        phi = zstore(iglob1)
+
+         ! precompute some products to reduce the CPU time
+        
+        costheta = cos(theta)
+        sintheta = sin(theta)
+        cosphi = cos(phi)
+        sinphi = sin(phi)
+
+        costhetasq = costheta * costheta
+        sinthetasq = sintheta * sintheta
+        cosphisq = cosphi * cosphi
+        sinphisq = sinphi * sinphi
+
+        costhetafour = costhetasq * costhetasq
+        sinthetafour = sinthetasq * sinthetasq
+        cosphifour = cosphisq * cosphisq
+        sinphifour = sinphisq * sinphisq
+
+        costwotheta = cos(2.0*theta)
+        sintwotheta = sin(2.0*theta)
+        costwophi = cos(2.0*phi)
+        sintwophi = sin(2.0*phi)
+
+        cosfourtheta = cos(4.0*theta)
+        cosfourphi = cos(4.0*phi)
+
+        costwothetasq = costwotheta * costwotheta
+
+        costwophisq = costwophi * costwophi
+        sintwophisq = sintwophi * sintwophi
+
+        etaminone = eta_aniso - 1.0
+        twoetaminone = 2.0 * eta_aniso - 1.0
+
+        ! precompute some products to reduce the CPU time
+        two_eta_aniso = 2.0*eta_aniso
+        four_eta_aniso = 4.0*eta_aniso
+        six_eta_aniso = 6.0*eta_aniso
+
+        two_rhovsvsq = 2.0*rhovsvsq
+        two_rhovshsq = 2.0*rhovshsq
+        four_rhovsvsq = 4.0*rhovsvsq
+        four_rhovshsq = 4.0*rhovshsq
+
+
+        ! way 2: pre-compute temporary values
+        templ1 = four_rhovsvsq - rhovpvsq + twoetaminone*rhovphsq - four_eta_aniso*rhovsvsq
+        templ1_cos = rhovphsq - rhovpvsq + costwotheta*templ1              
+        templ2 = four_rhovsvsq - rhovpvsq - rhovphsq + two_eta_aniso*rhovphsq - four_eta_aniso*rhovsvsq
+        templ2_cos = rhovpvsq - rhovphsq + costwotheta*templ2              
+        templ3 = rhovphsq + rhovpvsq - two_eta_aniso*rhovphsq + four_eta_aniso*rhovsvsq
+        templ3_two = templ3 - two_rhovshsq - two_rhovsvsq   
+        templ3_cos = templ3_two + costwotheta*templ2
+
+        ! way 2: reordering operations to facilitate compilation, avoiding divisions, using locality for temporary values
+        c11 = rhovphsq*sinphifour &
+              + 2.0*cosphisq*sinphisq* &
+              ( rhovphsq*costhetasq + sinthetasq*(eta_aniso*rhovphsq + two_rhovsvsq - two_eta_aniso*rhovsvsq) ) &
+              + cosphifour*(rhovphsq*costhetafour &
+                + 2.0*costhetasq*sinthetasq*(eta_aniso*rhovphsq + two_rhovsvsq - two_eta_aniso*rhovsvsq) &
+                + rhovpvsq*sinthetafour)
+
+        c12 = 0.25*costhetasq*(rhovphsq - two_rhovshsq)*(3.0 + cosfourphi) &
+              - four_rhovshsq*cosphisq*costhetasq*sinphisq &
+              + 0.03125*rhovphsq*sintwophisq*(11.0 + cosfourtheta + 4.0*costwotheta) &
+              + eta_aniso*sinthetasq*(rhovphsq - two_rhovsvsq) &
+                         *(cosphifour + sinphifour + 2.0*cosphisq*costhetasq*sinphisq) &
+              + rhovpvsq*cosphisq*sinphisq*sinthetafour &
+              - rhovsvsq*sintwophisq*sinthetafour
+
+        c13 = 0.125*cosphisq*(rhovphsq + six_eta_aniso*rhovphsq + rhovpvsq - four_rhovsvsq &
+                    - 12.0*eta_aniso*rhovsvsq + cosfourtheta*templ1) &
+              + sinphisq*(eta_aniso*costhetasq*(rhovphsq - two_rhovsvsq) + sinthetasq*(rhovphsq - two_rhovshsq))
+
+        ! uses temporary templ1 from c13
+        c15 = cosphi*costheta*sintheta* &
+              ( 0.5*cosphisq* (rhovpvsq - rhovphsq + costwotheta*templ1) &
+                + etaminone*sinphisq*(rhovphsq - two_rhovsvsq))
+
+        c14 = costheta*sinphi*sintheta* &
+              ( 0.5*cosphisq*(templ2_cos + four_rhovshsq - four_rhovsvsq) &
+                + sinphisq*(etaminone*rhovphsq + 2.0*(rhovshsq - eta_aniso*rhovsvsq)) )
+
+        ! uses temporary templ2_cos from c14              
+        c16 = 0.5*cosphi*sinphi*sinthetasq* &
+              ( cosphisq*templ2_cos &
+                + 2.0*etaminone*sinphisq*(rhovphsq - two_rhovsvsq) )
+
+        c22 = rhovphsq*cosphifour + 2.0*cosphisq*sinphisq* &
+              (rhovphsq*costhetasq + sinthetasq*(eta_aniso*rhovphsq + two_rhovsvsq - two_eta_aniso*rhovsvsq)) &
+              + sinphifour* &
+              (rhovphsq*costhetafour + 2.0*costhetasq*sinthetasq*(eta_aniso*rhovphsq  &
+                    + two_rhovsvsq - two_eta_aniso*rhovsvsq) + rhovpvsq*sinthetafour)
+        
+        ! uses temporary templ1 from c13
+        c23 = 0.125*sinphisq*(rhovphsq + six_eta_aniso*rhovphsq &
+                + rhovpvsq - four_rhovsvsq - 12.0*eta_aniso*rhovsvsq + cosfourtheta*templ1) &
+              + cosphisq*(eta_aniso*costhetasq*(rhovphsq - two_rhovsvsq) + sinthetasq*(rhovphsq - two_rhovshsq))
+    
+        ! uses temporary templ1 from c13 
+        c24 = costheta*sinphi*sintheta* &
+              ( etaminone*cosphisq*(rhovphsq - two_rhovsvsq) &
+                + 0.5*sinphisq*(rhovpvsq - rhovphsq + costwotheta*templ1) )
+
+        ! uses temporary templ2_cos from c14  
+        c25 = cosphi*costheta*sintheta* &
+              ( cosphisq*(etaminone*rhovphsq + 2.0*(rhovshsq - eta_aniso*rhovsvsq)) &
+                + 0.5*sinphisq*(templ2_cos + four_rhovshsq - four_rhovsvsq) )
+
+        ! uses temporary templ2_cos from c14
+        c26 = 0.5*cosphi*sinphi*sinthetasq* &
+              ( 2.0*etaminone*cosphisq*(rhovphsq - two_rhovsvsq) &
+                + sinphisq*templ2_cos ) 
+
+        c33 = rhovpvsq*costhetafour &
+              + 2.0*costhetasq*sinthetasq*(two_rhovsvsq + eta_aniso*(rhovphsq - two_rhovsvsq)) &
+              + rhovphsq*sinthetafour            
+        
+        ! uses temporary templ1_cos from c13
+        c34 = - 0.25*sinphi*sintwotheta*templ1_cos              
+
+        ! uses temporary templ1_cos from c34      
+        c35 = - 0.25*cosphi*sintwotheta*templ1_cos
+        
+        ! uses temporary templ1_cos from c34
+        c36 = - 0.25*sintwophi*sinthetasq*(templ1_cos - four_rhovshsq + four_rhovsvsq)              
+
+        c44 = cosphisq*(rhovsvsq*costhetasq + rhovshsq*sinthetasq) &
+              + sinphisq*(rhovsvsq*costwothetasq + costhetasq*sinthetasq*templ3)
+                      
+        ! uses temporary templ3 from c44     
+        c46 = - cosphi*costheta*sintheta* &
+                ( cosphisq*(rhovshsq - rhovsvsq) - 0.5*sinphisq*templ3_cos  )
+
+        ! uses templ3 from c46 
+        c45 = 0.25*sintwophi*sinthetasq* &
+              (templ3_two + costwotheta*(rhovphsq + rhovpvsq - two_eta_aniso*rhovphsq + 4.0*etaminone*rhovsvsq))
+      
+        c55 = sinphisq*(rhovsvsq*costhetasq + rhovshsq*sinthetasq) &
+              + cosphisq*(rhovsvsq*costwothetasq &
+                  + costhetasq*sinthetasq*(rhovphsq - two_eta_aniso*rhovphsq + rhovpvsq + four_eta_aniso*rhovsvsq) )
+                      
+        ! uses temporary templ3_cos from c46
+        c56 = costheta*sinphi*sintheta* &
+              ( 0.5*cosphisq*templ3_cos + sinphisq*(rhovsvsq - rhovshsq) )                            
+
+        c66 = rhovshsq*costwophisq*costhetasq &
+              - 2.0*cosphisq*costhetasq*sinphisq*(rhovphsq - two_rhovshsq) &
+              + 0.03125*rhovphsq*sintwophisq*(11.0 + 4.0*costwotheta + cosfourtheta) &
+              - 0.125*rhovsvsq*sinthetasq*( -6.0 - 2.0*costwotheta - 2.0*cosfourphi &
+                        + cos(4.0*phi - 2.0*theta) + cos(2.0*(2.0*phi + theta)) ) &
+              + rhovpvsq*cosphisq*sinphisq*sinthetafour &
+              - 0.5*eta_aniso*sintwophisq*sinthetafour*(rhovphsq - two_rhovsvsq)
+        
+
+        ! general expression of stress tensor for full Cijkl with 21 coefficients
+        sigma_xx = c11*duxdxl + c16*duxdyl_plus_duydxl + c12*duydyl + &
+                 c15*duzdxl_plus_duxdzl + c14*duzdyl_plus_duydzl + c13*duzdzl
+
+        sigma_yy = c12*duxdxl + c26*duxdyl_plus_duydxl + c22*duydyl + &
+                 c25*duzdxl_plus_duxdzl + c24*duzdyl_plus_duydzl + c23*duzdzl
+
+        sigma_zz = c13*duxdxl + c36*duxdyl_plus_duydxl + c23*duydyl + &
+                 c35*duzdxl_plus_duxdzl + c34*duzdyl_plus_duydzl + c33*duzdzl
+
+        sigma_xy = c16*duxdxl + c66*duxdyl_plus_duydxl + c26*duydyl + &
+                 c56*duzdxl_plus_duxdzl + c46*duzdyl_plus_duydzl + c36*duzdzl
+
+        sigma_xz = c15*duxdxl + c56*duxdyl_plus_duydxl + c25*duydyl + &
+                 c55*duzdxl_plus_duxdzl + c45*duzdyl_plus_duydzl + c35*duzdzl
+
+        sigma_yz = c14*duxdxl + c46*duxdyl_plus_duydxl + c24*duydyl + &
+                 c45*duzdxl_plus_duxdzl + c44*duzdyl_plus_duydzl + c34*duzdzl
+
+        ! subtract memory variables if attenuation
+        if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. )  ) then
+        
+          ! note: fortran passes pointers to array location, thus R_memory(1,1,...) should be fine
+          call compute_element_att_stress( R_memory(1,1,i,j,k,ispec), &
+                    sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz)
+        
+        endif ! ATTENUATION_VAL
+
+        ! define symmetric components of sigma for gravity
+        sigma_yx = sigma_xy
+        sigma_zx = sigma_xz
+        sigma_zy = sigma_yz
+
+        ! compute non-symmetric terms for gravity
+        if(GRAVITY_VAL) then
+
+             ! use mesh coordinates to get theta and phi
+            ! x y and z contain r theta and phi
+            iglob1 = ibool(i,j,k,ispec)
+
+            dtheta = dble(ystore(iglob1))
+            dphi = dble(zstore(iglob1))
+            radius = dble(xstore(iglob1))
+
+            cos_theta = dcos(dtheta)
+            sin_theta = dsin(dtheta)
+            cos_phi = dcos(dphi)
+            sin_phi = dsin(dphi)
+
+            ! way 2
+            cos_theta_sq = cos_theta*cos_theta
+            sin_theta_sq = sin_theta*sin_theta
+            cos_phi_sq = cos_phi*cos_phi
+            sin_phi_sq = sin_phi*sin_phi
+
+            ! get g, rho and dg/dr=dg
+            ! spherical components of the gravitational acceleration
+            ! for efficiency replace with lookup table every 100 m in radial direction
+            int_radius = nint(10.d0 * radius * R_EARTH_KM )
+            minus_g = minus_gravity_table(int_radius)
+            minus_dg = minus_deriv_gravity_table(int_radius)
+            rho = density_table(int_radius)
+
+            ! Cartesian components of the gravitational acceleration
+            gxl = minus_g*sin_theta*cos_phi
+            gyl = minus_g*sin_theta*sin_phi
+            gzl = minus_g*cos_theta
+
+            ! Cartesian components of gradient of gravitational acceleration
+            ! obtained from spherical components
+            minus_g_over_radius = minus_g / radius
+            minus_dg_plus_g_over_radius = minus_dg - minus_g_over_radius
+
+            Hxxl = minus_g_over_radius*(cos_phi_sq*cos_theta_sq + sin_phi_sq) + cos_phi_sq*minus_dg*sin_theta_sq
+            Hyyl = minus_g_over_radius*(cos_phi_sq + cos_theta_sq*sin_phi_sq) + minus_dg*sin_phi_sq*sin_theta_sq
+            Hzzl = cos_theta_sq*minus_dg + minus_g_over_radius*sin_theta_sq
+            Hxyl = cos_phi*minus_dg_plus_g_over_radius*sin_phi*sin_theta_sq
+            Hxzl = cos_phi*cos_theta*minus_dg_plus_g_over_radius*sin_theta
+            Hyzl = cos_theta*minus_dg_plus_g_over_radius*sin_phi*sin_theta
+
+            ! distinguish between single and double precision for reals
+            if(CUSTOM_REAL == SIZE_REAL) then
+
+              ! get displacement and multiply by density to compute G tensor
+              sx_l = rho * dble(dummyx_loc(i,j,k))
+              sy_l = rho * dble(dummyy_loc(i,j,k))
+              sz_l = rho * dble(dummyz_loc(i,j,k))
+
+
+              ! compute G tensor from s . g and add to sigma (not symmetric)
+              sigma_xx = sigma_xx + sngl(sy_l*gyl + sz_l*gzl)
+              sigma_yy = sigma_yy + sngl(sx_l*gxl + sz_l*gzl)
+              sigma_zz = sigma_zz + sngl(sx_l*gxl + sy_l*gyl)
+
+              sigma_xy = sigma_xy - sngl(sx_l * gyl)
+              sigma_yx = sigma_yx - sngl(sy_l * gxl)
+
+              sigma_xz = sigma_xz - sngl(sx_l * gzl)
+              sigma_zx = sigma_zx - sngl(sz_l * gxl)
+
+              sigma_yz = sigma_yz - sngl(sy_l * gzl)
+              sigma_zy = sigma_zy - sngl(sz_l * gyl)
+
+              ! precompute vector
+              factor = dble(jacobianl) * wgll_cube(i,j,k)
+              rho_s_H(1,i,j,k) = sngl(factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl))
+              rho_s_H(2,i,j,k) = sngl(factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl))
+              rho_s_H(3,i,j,k) = sngl(factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl))
+
+            else
+
+              ! get displacement and multiply by density to compute G tensor
+              sx_l = rho * dummyx_loc(i,j,k)
+              sy_l = rho * dummyy_loc(i,j,k)
+              sz_l = rho * dummyz_loc(i,j,k)
+
+              ! compute G tensor from s . g and add to sigma (not symmetric)
+              sigma_xx = sigma_xx + sy_l*gyl + sz_l*gzl
+              sigma_yy = sigma_yy + sx_l*gxl + sz_l*gzl
+              sigma_zz = sigma_zz + sx_l*gxl + sy_l*gyl
+
+              sigma_xy = sigma_xy - sx_l * gyl
+              sigma_yx = sigma_yx - sy_l * gxl
+
+              sigma_xz = sigma_xz - sx_l * gzl
+              sigma_zx = sigma_zx - sz_l * gxl
+
+              sigma_yz = sigma_yz - sy_l * gzl
+              sigma_zy = sigma_zy - sz_l * gyl
+
+              ! precompute vector
+              factor = jacobianl * wgll_cube(i,j,k)
+              rho_s_H(1,i,j,k) = factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl)
+              rho_s_H(2,i,j,k) = factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl)
+              rho_s_H(3,i,j,k) = factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl)
+
+            endif
+
+        endif  ! end of section with gravity terms
+
+        ! form dot product with test vector, non-symmetric form
+        tempx1(i,j,k) = jacobianl * (sigma_xx*xixl + sigma_yx*xiyl + sigma_zx*xizl)
+        tempy1(i,j,k) = jacobianl * (sigma_xy*xixl + sigma_yy*xiyl + sigma_zy*xizl)
+        tempz1(i,j,k) = jacobianl * (sigma_xz*xixl + sigma_yz*xiyl + sigma_zz*xizl)
+
+        tempx2(i,j,k) = jacobianl * (sigma_xx*etaxl + sigma_yx*etayl + sigma_zx*etazl)
+        tempy2(i,j,k) = jacobianl * (sigma_xy*etaxl + sigma_yy*etayl + sigma_zy*etazl)
+        tempz2(i,j,k) = jacobianl * (sigma_xz*etaxl + sigma_yz*etayl + sigma_zz*etazl)
+
+        tempx3(i,j,k) = jacobianl * (sigma_xx*gammaxl + sigma_yx*gammayl + sigma_zx*gammazl)
+        tempy3(i,j,k) = jacobianl * (sigma_xy*gammaxl + sigma_yy*gammayl + sigma_zy*gammazl)
+        tempz3(i,j,k) = jacobianl * (sigma_xz*gammaxl + sigma_yz*gammayl + sigma_zz*gammazl)
+      enddo ! NGLLX
+    enddo ! NGLLY
+  enddo ! NGLLZ
+  
+        
+  end subroutine compute_element_tiso
+  
+!
+!--------------------------------------------------------------------------------------------
+!
+
+
+  subroutine compute_element_aniso(ispec, &
+                    minus_gravity_table,density_table,minus_deriv_gravity_table, &
+                    xstore,ystore,zstore, &
+                    xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+                    wgll_cube, &
+                    c11store,c12store,c13store,c14store,c15store,c16store,c22store, &
+                    c23store,c24store,c25store,c26store,c33store,c34store,c35store, &
+                    c36store,c44store,c45store,c46store,c55store,c56store,c66store, &
+                    ibool, &
+                    R_memory,epsilon_trace_over_3, &
+                    one_minus_sum_beta,vx,vy,vz,vnspec, &
+                    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3, &
+                    dummyx_loc,dummyy_loc,dummyz_loc,epsilondev_loc,rho_s_H)
+          
+
+! this routine is optimized for NGLLX = NGLLY = NGLLZ = 5 using the Deville et al. (2002) inlined matrix-matrix products
+
+  implicit none
+
+  include "constants.h"
+
+  ! include values created by the mesher
+  ! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! element id
+  integer :: ispec
+
+  ! arrays with mesh parameters per slice
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool
+
+  ! x y and z contain r theta and phi
+  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: xstore,ystore,zstore
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: &
+        xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz
+
+  ! array with derivatives of Lagrange polynomials and precalculated products
+  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
+
+  ! arrays for full anisotropy only when needed
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_MANTLE) :: &
+        c11store,c12store,c13store,c14store,c15store,c16store,c22store, &
+        c23store,c24store,c25store,c26store,c33store,c34store,c35store, &
+        c36store,c44store,c45store,c46store,c55store,c56store,c66store
+
+  ! attenuation
+  ! memory variables for attenuation
+  ! memory variables R_ij are stored at the local rather than global level
+  ! to allow for optimization of cache access by compiler
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory
+  real(kind=CUSTOM_REAL),dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilon_trace_over_3
+
+  integer vx,vy,vz,vnspec
+
+  ! [alpha,beta,gamma]val reduced to N_SLS  to N_SLS*NUM_NODES
+  real(kind=CUSTOM_REAL), dimension(vx, vy, vz, vnspec) :: one_minus_sum_beta
+
+  ! gravity
+  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table,density_table,minus_deriv_gravity_table
+
+  ! element info
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: &
+    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: dummyx_loc,dummyy_loc,dummyz_loc
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: rho_s_H
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
+
+! local parameters
+  real(kind=CUSTOM_REAL) one_minus_sum_beta_use
+  real(kind=CUSTOM_REAL) minus_sum_beta,mul
+  ! the 21 coefficients for an anisotropic medium in reduced notation
+  real(kind=CUSTOM_REAL) c11,c22,c33,c44,c55,c66,c12,c13,c23,c14,c24,c34,c15,c25,c35,c45,c16,c26,c36,c46,c56
+
+  real(kind=CUSTOM_REAL) xixl,xiyl,xizl,etaxl,etayl,etazl,gammaxl,gammayl,gammazl,jacobianl
+  real(kind=CUSTOM_REAL) duxdxl,duxdyl,duxdzl,duydxl,duydyl,duydzl,duzdxl,duzdyl,duzdzl
+  real(kind=CUSTOM_REAL) duxdxl_plus_duydyl,duxdxl_plus_duzdzl,duydyl_plus_duzdzl
+  real(kind=CUSTOM_REAL) duxdyl_plus_duydxl,duzdxl_plus_duxdzl,duzdyl_plus_duydzl
+  real(kind=CUSTOM_REAL) sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz
+
+  real(kind=CUSTOM_REAL) templ
+
+  ! for gravity
+  double precision dphi,dtheta
+  double precision radius,rho,minus_g,minus_dg
+  double precision minus_g_over_radius,minus_dg_plus_g_over_radius
+  double precision cos_theta,sin_theta,cos_phi,sin_phi
+  double precision cos_theta_sq,sin_theta_sq,cos_phi_sq,sin_phi_sq
+  double precision factor,sx_l,sy_l,sz_l,gxl,gyl,gzl
+  double precision Hxxl,Hyyl,Hzzl,Hxyl,Hxzl,Hyzl
+  real(kind=CUSTOM_REAL) sigma_yx,sigma_zx,sigma_zy
+
+  integer :: ispec_strain
+  integer :: i,j,k
+  integer :: int_radius
+  integer :: iglob1
+  
+  !  anisotropic elements
+
+  do k=1,NGLLZ
+    do j=1,NGLLY
+      do i=1,NGLLX
+        ! get derivatives of ux, uy and uz with respect to x, y and z
+        xixl = xix(i,j,k,ispec)
+        xiyl = xiy(i,j,k,ispec)
+        xizl = xiz(i,j,k,ispec)
+        etaxl = etax(i,j,k,ispec)
+        etayl = etay(i,j,k,ispec)
+        etazl = etaz(i,j,k,ispec)
+        gammaxl = gammax(i,j,k,ispec)
+        gammayl = gammay(i,j,k,ispec)
+        gammazl = gammaz(i,j,k,ispec)
+
+        ! compute the jacobian
+        jacobianl = 1._CUSTOM_REAL / (xixl*(etayl*gammazl-etazl*gammayl) &
+                      - xiyl*(etaxl*gammazl-etazl*gammaxl) &
+                      + xizl*(etaxl*gammayl-etayl*gammaxl))
+
+        duxdxl = xixl*tempx1(i,j,k) + etaxl*tempx2(i,j,k) + gammaxl*tempx3(i,j,k)
+        duxdyl = xiyl*tempx1(i,j,k) + etayl*tempx2(i,j,k) + gammayl*tempx3(i,j,k)
+        duxdzl = xizl*tempx1(i,j,k) + etazl*tempx2(i,j,k) + gammazl*tempx3(i,j,k)
+
+        duydxl = xixl*tempy1(i,j,k) + etaxl*tempy2(i,j,k) + gammaxl*tempy3(i,j,k)
+        duydyl = xiyl*tempy1(i,j,k) + etayl*tempy2(i,j,k) + gammayl*tempy3(i,j,k)
+        duydzl = xizl*tempy1(i,j,k) + etazl*tempy2(i,j,k) + gammazl*tempy3(i,j,k)
+
+        duzdxl = xixl*tempz1(i,j,k) + etaxl*tempz2(i,j,k) + gammaxl*tempz3(i,j,k)
+        duzdyl = xiyl*tempz1(i,j,k) + etayl*tempz2(i,j,k) + gammayl*tempz3(i,j,k)
+        duzdzl = xizl*tempz1(i,j,k) + etazl*tempz2(i,j,k) + gammazl*tempz3(i,j,k)
+
+        ! precompute some sums to save CPU time
+        duxdxl_plus_duydyl = duxdxl + duydyl
+        duxdxl_plus_duzdzl = duxdxl + duzdzl
+        duydyl_plus_duzdzl = duydyl + duzdzl
+        duxdyl_plus_duydxl = duxdyl + duydxl
+        duzdxl_plus_duxdzl = duzdxl + duxdzl
+        duzdyl_plus_duydzl = duzdyl + duydzl
+
+        ! compute deviatoric strain
+        if (COMPUTE_AND_STORE_STRAIN) then
+          if(NSPEC_CRUST_MANTLE_STRAIN_ONLY == 1) then
+            ispec_strain = 1
+          else
+            ispec_strain = ispec
+          endif
+          templ = ONE_THIRD * (duxdxl + duydyl + duzdzl)
+          epsilon_trace_over_3(i,j,k,ispec_strain) = templ
+          epsilondev_loc(1,i,j,k) = duxdxl - templ
+          epsilondev_loc(2,i,j,k) = duydyl - templ
+          epsilondev_loc(3,i,j,k) = 0.5 * duxdyl_plus_duydxl
+          epsilondev_loc(4,i,j,k) = 0.5 * duzdxl_plus_duxdzl
+          epsilondev_loc(5,i,j,k) = 0.5 * duzdyl_plus_duydzl
+        endif
+
+        ! precompute terms for attenuation if needed
+        if(ATTENUATION_VAL) then
+          one_minus_sum_beta_use = one_minus_sum_beta(i,j,k,ispec)
+          minus_sum_beta =  one_minus_sum_beta_use - 1.0
+        endif
+
+        !
+        ! compute anisotropic elements
+        !
+
+        c11 = c11store(i,j,k,ispec)
+        c12 = c12store(i,j,k,ispec)
+        c13 = c13store(i,j,k,ispec)
+        c14 = c14store(i,j,k,ispec)
+        c15 = c15store(i,j,k,ispec)
+        c16 = c16store(i,j,k,ispec)
+        c22 = c22store(i,j,k,ispec)
+        c23 = c23store(i,j,k,ispec)
+        c24 = c24store(i,j,k,ispec)
+        c25 = c25store(i,j,k,ispec)
+        c26 = c26store(i,j,k,ispec)
+        c33 = c33store(i,j,k,ispec)
+        c34 = c34store(i,j,k,ispec)
+        c35 = c35store(i,j,k,ispec)
+        c36 = c36store(i,j,k,ispec)
+        c44 = c44store(i,j,k,ispec)
+        c45 = c45store(i,j,k,ispec)
+        c46 = c46store(i,j,k,ispec)
+        c55 = c55store(i,j,k,ispec)
+        c56 = c56store(i,j,k,ispec)
+        c66 = c66store(i,j,k,ispec)
+
+        if(ATTENUATION_VAL) then
+          !mul = c44
+          mul = c44 * minus_sum_beta
+          c11 = c11 + FOUR_THIRDS * mul ! * minus_sum_beta * mul
+          c12 = c12 - TWO_THIRDS * mul
+          c13 = c13 - TWO_THIRDS * mul
+          c22 = c22 + FOUR_THIRDS * mul
+          c23 = c23 - TWO_THIRDS * mul
+          c33 = c33 + FOUR_THIRDS * mul
+          c44 = c44 + mul
+          c55 = c55 + mul
+          c66 = c66 + mul
+        endif
+
+        sigma_xx = c11*duxdxl + c16*duxdyl_plus_duydxl + c12*duydyl + &
+                 c15*duzdxl_plus_duxdzl + c14*duzdyl_plus_duydzl + c13*duzdzl
+
+        sigma_yy = c12*duxdxl + c26*duxdyl_plus_duydxl + c22*duydyl + &
+                 c25*duzdxl_plus_duxdzl + c24*duzdyl_plus_duydzl + c23*duzdzl
+
+        sigma_zz = c13*duxdxl + c36*duxdyl_plus_duydxl + c23*duydyl + &
+                 c35*duzdxl_plus_duxdzl + c34*duzdyl_plus_duydzl + c33*duzdzl
+
+        sigma_xy = c16*duxdxl + c66*duxdyl_plus_duydxl + c26*duydyl + &
+                 c56*duzdxl_plus_duxdzl + c46*duzdyl_plus_duydzl + c36*duzdzl
+
+        sigma_xz = c15*duxdxl + c56*duxdyl_plus_duydxl + c25*duydyl + &
+                 c55*duzdxl_plus_duxdzl + c45*duzdyl_plus_duydzl + c35*duzdzl
+
+        sigma_yz = c14*duxdxl + c46*duxdyl_plus_duydxl + c24*duydyl + &
+                 c45*duzdxl_plus_duxdzl + c44*duzdyl_plus_duydzl + c34*duzdzl
+
+        ! subtract memory variables if attenuation
+        if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. )  ) then
+
+          ! note: fortran passes pointers to array location, thus R_memory(1,1,...) should be fine
+          call compute_element_att_stress( R_memory(1,1,i,j,k,ispec), &
+                    sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz)
+
+        endif ! ATTENUATION_VAL
+
+        ! define symmetric components of sigma for gravity
+        sigma_yx = sigma_xy
+        sigma_zx = sigma_xz
+        sigma_zy = sigma_yz
+
+        ! compute non-symmetric terms for gravity
+        if(GRAVITY_VAL) then
+
+             ! use mesh coordinates to get theta and phi
+            ! x y and z contain r theta and phi
+            iglob1 = ibool(i,j,k,ispec)
+
+            dtheta = dble(ystore(iglob1))
+            dphi = dble(zstore(iglob1))
+            radius = dble(xstore(iglob1))
+
+            cos_theta = dcos(dtheta)
+            sin_theta = dsin(dtheta)
+            cos_phi = dcos(dphi)
+            sin_phi = dsin(dphi)
+
+            cos_theta_sq = cos_theta*cos_theta
+            sin_theta_sq = sin_theta*sin_theta
+            cos_phi_sq = cos_phi*cos_phi
+            sin_phi_sq = sin_phi*sin_phi
+
+            ! get g, rho and dg/dr=dg
+            ! spherical components of the gravitational acceleration
+            ! for efficiency replace with lookup table every 100 m in radial direction
+            int_radius = nint(10.d0 * radius * R_EARTH_KM )
+            minus_g = minus_gravity_table(int_radius)
+            minus_dg = minus_deriv_gravity_table(int_radius)
+            rho = density_table(int_radius)
+
+            ! Cartesian components of the gravitational acceleration
+            gxl = minus_g*sin_theta*cos_phi
+            gyl = minus_g*sin_theta*sin_phi
+            gzl = minus_g*cos_theta
+
+            ! Cartesian components of gradient of gravitational acceleration
+            ! obtained from spherical components
+            minus_g_over_radius = minus_g / radius
+            minus_dg_plus_g_over_radius = minus_dg - minus_g_over_radius
+
+            Hxxl = minus_g_over_radius*(cos_phi_sq*cos_theta_sq + sin_phi_sq) + cos_phi_sq*minus_dg*sin_theta_sq
+            Hyyl = minus_g_over_radius*(cos_phi_sq + cos_theta_sq*sin_phi_sq) + minus_dg*sin_phi_sq*sin_theta_sq
+            Hzzl = cos_theta_sq*minus_dg + minus_g_over_radius*sin_theta_sq
+            Hxyl = cos_phi*minus_dg_plus_g_over_radius*sin_phi*sin_theta_sq
+            Hxzl = cos_phi*cos_theta*minus_dg_plus_g_over_radius*sin_theta
+            Hyzl = cos_theta*minus_dg_plus_g_over_radius*sin_phi*sin_theta
+
+            ! distinguish between single and double precision for reals
+            if(CUSTOM_REAL == SIZE_REAL) then
+
+              ! get displacement and multiply by density to compute G tensor
+              sx_l = rho * dble(dummyx_loc(i,j,k)) ! dble(displ_crust_mantle(1,iglob1))
+              sy_l = rho * dble(dummyy_loc(i,j,k)) ! dble(displ_crust_mantle(2,iglob1))
+              sz_l = rho * dble(dummyz_loc(i,j,k)) !  dble(displ_crust_mantle(3,iglob1))
+
+              ! compute G tensor from s . g and add to sigma (not symmetric)
+              sigma_xx = sigma_xx + sngl(sy_l*gyl + sz_l*gzl)
+              sigma_yy = sigma_yy + sngl(sx_l*gxl + sz_l*gzl)
+              sigma_zz = sigma_zz + sngl(sx_l*gxl + sy_l*gyl)
+
+              sigma_xy = sigma_xy - sngl(sx_l * gyl)
+              sigma_yx = sigma_yx - sngl(sy_l * gxl)
+
+              sigma_xz = sigma_xz - sngl(sx_l * gzl)
+              sigma_zx = sigma_zx - sngl(sz_l * gxl)
+
+              sigma_yz = sigma_yz - sngl(sy_l * gzl)
+              sigma_zy = sigma_zy - sngl(sz_l * gyl)
+
+              ! precompute vector
+              factor = dble(jacobianl) * wgll_cube(i,j,k)
+              rho_s_H(1,i,j,k) = sngl(factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl))
+              rho_s_H(2,i,j,k) = sngl(factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl))
+              rho_s_H(3,i,j,k) = sngl(factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl))
+
+            else
+
+              ! get displacement and multiply by density to compute G tensor
+              sx_l = rho * dummyx_loc(i,j,k)  ! displ_crust_mantle(1,iglob1)
+              sy_l = rho * dummyy_loc(i,j,k)  !  displ_crust_mantle(2,iglob1)
+              sz_l = rho * dummyz_loc(i,j,k)  ! displ_crust_mantle(3,iglob1)
+
+              ! compute G tensor from s . g and add to sigma (not symmetric)
+              sigma_xx = sigma_xx + sy_l*gyl + sz_l*gzl
+              sigma_yy = sigma_yy + sx_l*gxl + sz_l*gzl
+              sigma_zz = sigma_zz + sx_l*gxl + sy_l*gyl
+
+              sigma_xy = sigma_xy - sx_l * gyl
+              sigma_yx = sigma_yx - sy_l * gxl
+
+              sigma_xz = sigma_xz - sx_l * gzl
+              sigma_zx = sigma_zx - sz_l * gxl
+
+              sigma_yz = sigma_yz - sy_l * gzl
+              sigma_zy = sigma_zy - sz_l * gyl
+
+              ! precompute vector
+              factor = jacobianl * wgll_cube(i,j,k)
+              rho_s_H(1,i,j,k) = factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl)
+              rho_s_H(2,i,j,k) = factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl)
+              rho_s_H(3,i,j,k) = factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl)
+
+            endif
+
+        endif  ! end of section with gravity terms
+
+        ! form dot product with test vector, non-symmetric form
+        tempx1(i,j,k) = jacobianl * (sigma_xx*xixl + sigma_yx*xiyl + sigma_zx*xizl)
+        tempy1(i,j,k) = jacobianl * (sigma_xy*xixl + sigma_yy*xiyl + sigma_zy*xizl)
+        tempz1(i,j,k) = jacobianl * (sigma_xz*xixl + sigma_yz*xiyl + sigma_zz*xizl)
+
+        tempx2(i,j,k) = jacobianl * (sigma_xx*etaxl + sigma_yx*etayl + sigma_zx*etazl)
+        tempy2(i,j,k) = jacobianl * (sigma_xy*etaxl + sigma_yy*etayl + sigma_zy*etazl)
+        tempz2(i,j,k) = jacobianl * (sigma_xz*etaxl + sigma_yz*etayl + sigma_zz*etazl)
+
+        tempx3(i,j,k) = jacobianl * (sigma_xx*gammaxl + sigma_yx*gammayl + sigma_zx*gammazl)
+        tempy3(i,j,k) = jacobianl * (sigma_xy*gammaxl + sigma_yy*gammayl + sigma_zy*gammazl)
+        tempz3(i,j,k) = jacobianl * (sigma_xz*gammaxl + sigma_yz*gammayl + sigma_zz*gammazl)
+      enddo ! NGLLX
+    enddo ! NGLLY
+  enddo ! NGLLZ    
+        
+  end subroutine compute_element_aniso
+
+!
+!--------------------------------------------------------------------------------------------
+!
+
+
+  subroutine compute_element_att_stress( R_memory_loc, &
+                    sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz)
+          
+  implicit none
+
+  include "constants.h"
+
+  ! include values created by the mesher
+  ! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! attenuation
+  ! memory variables for attenuation
+  ! memory variables R_ij are stored at the local rather than global level
+  ! to allow for optimization of cache access by compiler
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS) :: R_memory_loc
+  real(kind=CUSTOM_REAL) sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz
+
+! local parameters
+  real(kind=CUSTOM_REAL) R_xx_val1,R_yy_val1
+  integer :: i_SLS
+#ifdef _HANDOPT
+  real(kind=CUSTOM_REAL) R_xx_val2,R_yy_val2,R_xx_val3,R_yy_val3
+  integer :: imodulo_N_SLS
+  integer :: i_SLS1,i_SLS2
+#endif
+  
+#ifdef _HANDOPT
+! way 2:
+! note: this should help compilers to pipeline the code and make better use of the cache;
+!          depending on compilers, it can further decrease the computation time by ~ 30%.
+!          by default, N_SLS = 3, therefore we take steps of 3
+  imodulo_N_SLS = mod(N_SLS,3)
+
+  if(imodulo_N_SLS >= 1) then
+    do i_SLS = 1,imodulo_N_SLS
+      R_xx_val1 = R_memory_loc(1,i_SLS) 
+      R_yy_val1 = R_memory_loc(2,i_SLS) 
+      sigma_xx = sigma_xx - R_xx_val1
+      sigma_yy = sigma_yy - R_yy_val1
+      sigma_zz = sigma_zz + R_xx_val1 + R_yy_val1
+      sigma_xy = sigma_xy - R_memory_loc(3,i_SLS) 
+      sigma_xz = sigma_xz - R_memory_loc(4,i_SLS) 
+      sigma_yz = sigma_yz - R_memory_loc(5,i_SLS) 
+    enddo
+  endif
+  if(N_SLS >= imodulo_N_SLS+1) then
+    ! note: another possibility would be using a reduction example for this loop; was tested but it does not improve, 
+    ! probably since N_SLS == 3 is too small for a loop benefit  
+    do i_SLS = imodulo_N_SLS+1,N_SLS,3
+      R_xx_val1 = R_memory_loc(1,i_SLS) 
+      R_yy_val1 = R_memory_loc(2,i_SLS) 
+      sigma_xx = sigma_xx - R_xx_val1
+      sigma_yy = sigma_yy - R_yy_val1
+      sigma_zz = sigma_zz + R_xx_val1 + R_yy_val1
+      sigma_xy = sigma_xy - R_memory_loc(3,i_SLS) 
+      sigma_xz = sigma_xz - R_memory_loc(4,i_SLS) 
+      sigma_yz = sigma_yz - R_memory_loc(5,i_SLS) 
+
+      i_SLS1=i_SLS+1
+      R_xx_val2 = R_memory_loc(1,i_SLS1) 
+      R_yy_val2 = R_memory_loc(2,i_SLS1) 
+      sigma_xx = sigma_xx - R_xx_val2
+      sigma_yy = sigma_yy - R_yy_val2
+      sigma_zz = sigma_zz + R_xx_val2 + R_yy_val2
+      sigma_xy = sigma_xy - R_memory_loc(3,i_SLS1) 
+      sigma_xz = sigma_xz - R_memory_loc(4,i_SLS1) 
+      sigma_yz = sigma_yz - R_memory_loc(5,i_SLS1) 
+
+      i_SLS2 =i_SLS+2
+      R_xx_val3 = R_memory_loc(1,i_SLS2) 
+      R_yy_val3 = R_memory_loc(2,i_SLS2) 
+      sigma_xx = sigma_xx - R_xx_val3
+      sigma_yy = sigma_yy - R_yy_val3
+      sigma_zz = sigma_zz + R_xx_val3 + R_yy_val3
+      sigma_xy = sigma_xy - R_memory_loc(3,i_SLS2) 
+      sigma_xz = sigma_xz - R_memory_loc(4,i_SLS2) 
+      sigma_yz = sigma_yz - R_memory_loc(5,i_SLS2)                                          
+    enddo    
+  endif     
+#else
+! way 1:
+  do i_SLS = 1,N_SLS
+    R_xx_val1 = R_memory_loc(1,i_SLS) ! R_memory(1,i_SLS,i,j,k,ispec)
+    R_yy_val1 = R_memory_loc(2,i_SLS) ! R_memory(2,i_SLS,i,j,k,ispec)
+    sigma_xx = sigma_xx - R_xx_val1
+    sigma_yy = sigma_yy - R_yy_val1
+    sigma_zz = sigma_zz + R_xx_val1 + R_yy_val1
+    sigma_xy = sigma_xy - R_memory_loc(3,i_SLS) ! R_memory(3,i_SLS,i,j,k,ispec)
+    sigma_xz = sigma_xz - R_memory_loc(4,i_SLS) ! R_memory(4,i_SLS,i,j,k,ispec)
+    sigma_yz = sigma_yz - R_memory_loc(5,i_SLS) ! R_memory(5,i_SLS,i,j,k,ispec)
+  enddo
+#endif
+
+  end subroutine compute_element_att_stress
+
+
+!
+!--------------------------------------------------------------------------------------------
+!
+
+  subroutine compute_element_att_memory_cr(ispec,R_memory, &
+                                        vx,vy,vz,vnspec,factor_common, &
+                                        alphaval,betaval,gammaval, &
+                                        c44store,muvstore, &
+                                        epsilondev,epsilondev_loc)
+! crust mantle          
+! update memory variables based upon the Runge-Kutta scheme
+
+! convention for attenuation
+! term in xx = 1
+! term in yy = 2
+! term in xy = 3
+! term in xz = 4
+! term in yz = 5
+! term in zz not computed since zero trace
+! This is because we only implement Q_\mu attenuation and not Q_\kappa.
+! Note that this does *NOT* imply that there is no attenuation for P waves
+! because for Q_\kappa = infinity one gets (see for instance Dahlen and Tromp (1998)
+! equation (9.59) page 350): Q_\alpha = Q_\mu * 3 * (V_p/V_s)^2 / 4
+! therefore Q_\alpha is not zero; for instance for V_p / V_s = sqrt(3)
+! we get Q_\alpha = (9 / 4) * Q_\mu = 2.25 * Q_\mu
+
+  implicit none
+
+  include "constants.h"
+
+  ! include values created by the mesher
+  ! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! element id
+  integer :: ispec
+  
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory
+
+  integer :: vx,vy,vz,vnspec
+  real(kind=CUSTOM_REAL), dimension(N_SLS, vx, vy, vz, vnspec) :: factor_common
+  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval,betaval,gammaval
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_MANTLE) :: c44store
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ISO_MANTLE) :: muvstore
+    
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilondev
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
+
+! local parameters  
+  real(kind=CUSTOM_REAL), dimension(NGLLX, NGLLY, NGLLZ) :: factor_common_c44_muv
+  integer :: i_SLS
+  
+#ifdef _HANDOPT
+  real(kind=CUSTOM_REAL) :: alphal,betal,gammal
+  integer :: i,j,k
+#else
+  integer :: i_memory
+#endif
+
+  ! use Runge-Kutta scheme to march in time
+
+  ! get coefficients for that standard linear solid
+  ! IMPROVE we use mu_v here even if there is some anisotropy
+  ! IMPROVE we should probably use an average value instead
+
+#ifdef _HANDOPT
+! way 2:    
+  do i_SLS = 1,N_SLS
+
+    alphal = alphaval(i_SLS)
+    betal = betaval(i_SLS)
+    gammal = gammaval(i_SLS)        
+
+    ! reformatted R_memory to handle large factor_common and reduced [alpha,beta,gamma]val
+    factor_common_c44_muv(:,:,:) = factor_common(i_SLS,:,:,:,ispec)
+
+    if(ANISOTROPIC_3D_MANTLE_VAL) then
+      factor_common_c44_muv(:,:,:) = factor_common_c44_muv(:,:,:) * c44store(:,:,:,ispec)
+    else
+      factor_common_c44_muv(:,:,:) = factor_common_c44_muv(:,:,:) * muvstore(:,:,:,ispec)
+    endif
+
+    ! this helps to vectorize the inner most loop
+    do k=1,NGLLZ
+      do j=1,NGLLY
+        do i=1,NGLLX
+          R_memory(:,i_SLS,i,j,k,ispec) = alphal * R_memory(:,i_SLS,i,j,k,ispec) &
+                  + factor_common_c44_muv(i,j,k) &
+                  *( betal * epsilondev(:,i,j,k,ispec) + gammal * epsilondev_loc(:,i,j,k))
+        enddo
+      enddo
+    enddo
+  enddo ! i_SLS
+#else
+! way 1:
+  do i_SLS = 1,N_SLS
+    ! reformatted R_memory to handle large factor_common and reduced [alpha,beta,gamma]val
+    factor_common_c44_muv(:,:,:) = factor_common(i_SLS,:,:,:,ispec)
+
+    if(ANISOTROPIC_3D_MANTLE_VAL) then
+      factor_common_c44_muv(:,:,:) = factor_common_c44_muv(:,:,:) * c44store(:,:,:,ispec)
+    else
+      factor_common_c44_muv(:,:,:) = factor_common_c44_muv(:,:,:) * muvstore(:,:,:,ispec)
+    endif
+
+    do i_memory = 1,5 
+      R_memory(i_memory,i_SLS,:,:,:,ispec) = alphaval(i_SLS) * R_memory(i_memory,i_SLS,:,:,:,ispec) &
+                + factor_common_c44_muv(:,:,:) &
+                * (betaval(i_SLS) * epsilondev(i_memory,:,:,:,ispec) + gammaval(i_SLS) * epsilondev_loc(i_memory,:,:,:))
+    enddo
+  enddo ! i_SLS
+#endif
+
+
+  end subroutine compute_element_att_memory_cr
+  
+!
+!--------------------------------------------------------------------------------------------
+!
+
+  subroutine compute_element_att_memory_ic(ispec,R_memory, &
+                                        vx,vy,vz,vnspec,factor_common, &
+                                        alphaval,betaval,gammaval, &
+                                        muvstore, &
+                                        epsilondev,epsilondev_loc)
+! inner core          
+! update memory variables based upon the Runge-Kutta scheme
+
+! convention for attenuation
+! term in xx = 1
+! term in yy = 2
+! term in xy = 3
+! term in xz = 4
+! term in yz = 5
+! term in zz not computed since zero trace
+! This is because we only implement Q_\mu attenuation and not Q_\kappa.
+! Note that this does *NOT* imply that there is no attenuation for P waves
+! because for Q_\kappa = infinity one gets (see for instance Dahlen and Tromp (1998)
+! equation (9.59) page 350): Q_\alpha = Q_\mu * 3 * (V_p/V_s)^2 / 4
+! therefore Q_\alpha is not zero; for instance for V_p / V_s = sqrt(3)
+! we get Q_\alpha = (9 / 4) * Q_\mu = 2.25 * Q_\mu
+
+  implicit none
+
+  include "constants.h"
+
+  ! include values created by the mesher
+  ! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! element id
+  integer :: ispec
+  
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ATTENUATION) :: R_memory
+
+  integer :: vx,vy,vz,vnspec
+  real(kind=CUSTOM_REAL), dimension(N_SLS, vx, vy, vz, vnspec) :: factor_common
+  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval,betaval,gammaval
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: muvstore
+    
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: epsilondev  
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
+
+! local parameters  
+  real(kind=CUSTOM_REAL), dimension(NGLLX, NGLLY, NGLLZ) :: factor_common_use
+  
+  integer :: i_SLS
+  
+#ifdef _HANDOPT
+  real(kind=CUSTOM_REAL) :: alphal,betal,gammal
+  integer :: i,j,k
+#else
+  integer :: i_memory
+#endif
+
+  ! use Runge-Kutta scheme to march in time
+
+  ! get coefficients for that standard linear solid
+  ! IMPROVE we use mu_v here even if there is some anisotropy
+  ! IMPROVE we should probably use an average value instead
+
+#ifdef _HANDOPT
+! way 2:
+  do i_SLS = 1,N_SLS
+
+    alphal = alphaval(i_SLS)
+    betal = betaval(i_SLS)
+    gammal = gammaval(i_SLS)        
+
+    ! reformatted R_memory to handle large factor_common and reduced [alpha,beta,gamma]val
+    factor_common_use(:,:,:) = factor_common(i_SLS,:,:,:,ispec) 
+    
+    factor_common_use(:,:,:) = factor_common_use(:,:,:) * muvstore(:,:,:,ispec)
+
+    ! this helps to vectorize the inner most loop
+    do k=1,NGLLZ
+      do j=1,NGLLY
+        do i=1,NGLLX
+          R_memory(:,i_SLS,i,j,k,ispec) = alphal * R_memory(:,i_SLS,i,j,k,ispec) &
+                  + factor_common_use(i,j,k) &
+                  *( betal * epsilondev(:,i,j,k,ispec) + gammal * epsilondev_loc(:,i,j,k))
+        enddo
+      enddo
+    enddo
+    
+  enddo ! i_SLS
+#else
+! way 1:
+  do i_SLS = 1,N_SLS
+    factor_common_use(:,:,:) = factor_common(i_SLS,:,:,:,ispec)
+    do i_memory = 1,5
+       R_memory(i_memory,i_SLS,:,:,:,ispec) = alphaval(i_SLS) * R_memory(i_memory,i_SLS,:,:,:,ispec) &
+            + muvstore(:,:,:,ispec) * factor_common_use(:,:,:) * &
+            (betaval(i_SLS) * epsilondev(i_memory,:,:,:,ispec) + gammaval(i_SLS) * epsilondev_loc(i_memory,:,:,:))
+    enddo
+  enddo
+#endif
+
+  end subroutine compute_element_att_memory_ic
+      
+    
\ No newline at end of file

Copied: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.F90 (from rev 18970, seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.f90)
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.F90	                        (rev 0)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.F90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -0,0 +1,594 @@
+!=====================================================================
+!
+!          S p e c f e m 3 D  G l o b e  V e r s i o n  5 . 1
+!          --------------------------------------------------
+!
+!          Main authors: Dimitri Komatitsch and Jeroen Tromp
+!                        Princeton University, USA
+!             and University of Pau / CNRS / INRIA, France
+! (c) Princeton University / California Institute of Technology and University of Pau / CNRS / INRIA
+!                            April 2011
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or
+! (at your option) any later version.
+!
+! This program is distributed in the hope that it will be useful,
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+! GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along
+! with this program; if not, write to the Free Software Foundation, Inc.,
+! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+!
+!=====================================================================
+
+! preprocessing definition: #define _HANDOPT :  turns hand-optimized code on
+!                                         #undef _HANDOPT :  turns hand-optimized code off
+! or compile with: -D_HANDOPT
+!#define _HANDOPT
+ 
+! note: these hand optimizations should help compilers to pipeline the code and make better use of the cache;
+!          depending on compilers, it can further decrease the computation time by ~ 30%.
+!          the original routines are commented with "! way 1", the hand-optimized routines with  "! way 2"
+
+  subroutine compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_crust_mantle,accel_crust_mantle,xstore,ystore,zstore, &
+          xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,icall, &
+            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_INNER_CORE,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT, &
+          hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore,kappahstore,muvstore,muhstore,eta_anisostore, &
+          c11store,c12store,c13store,c14store,c15store,c16store,c22store, &
+          c23store,c24store,c25store,c26store,c33store,c34store,c35store, &
+          c36store,c44store,c45store,c46store,c55store,c56store,c66store, &
+          ibool,ispec_is_tiso, &
+        ! --idoubling,
+          R_memory,epsilondev,epsilon_trace_over_3,one_minus_sum_beta, &
+          alphaval,betaval,gammaval,factor_common,vx,vy,vz,vnspec)
+
+! this routine is optimized for NGLLX = NGLLY = NGLLZ = 5 using the Deville et al. (2002) inlined matrix-matrix products
+
+  implicit none
+
+  include "constants.h"
+
+  ! include values created by the mesher
+  ! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! displacement and acceleration
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: displ_crust_mantle,accel_crust_mantle
+  ! arrays with mesh parameters per slice
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool
+
+  ! x y and z contain r theta and phi
+  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: xstore,ystore,zstore
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: &
+        xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz
+
+  ! array with derivatives of Lagrange polynomials and precalculated products
+  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xx,hprimewgll_xx
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xxT,hprimewgll_xxT
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY) :: wgllwgll_xy
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ) :: wgllwgll_xz
+  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ) :: wgllwgll_yz
+
+  ! store anisotropic properties only where needed to save memory
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_TISO_MANTLE) :: &
+        kappahstore,muhstore,eta_anisostore
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ISO_MANTLE) :: &
+        kappavstore,muvstore
+
+  ! arrays for full anisotropy only when needed
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_MANTLE) :: &
+        c11store,c12store,c13store,c14store,c15store,c16store,c22store, &
+        c23store,c24store,c25store,c26store,c33store,c34store,c35store, &
+        c36store,c44store,c45store,c46store,c55store,c56store,c66store
+
+  ! attenuation
+  ! memory variables for attenuation
+  ! memory variables R_ij are stored at the local rather than global level
+  ! to allow for optimization of cache access by compiler
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilondev
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilon_trace_over_3
+
+  integer :: vx,vy,vz,vnspec
+
+  ! [alpha,beta,gamma]val reduced to N_SLS and factor_common to N_SLS*NUM_NODES
+  real(kind=CUSTOM_REAL), dimension(N_SLS, vx, vy, vz, vnspec) :: factor_common
+  real(kind=CUSTOM_REAL), dimension(vx, vy, vz, vnspec) :: one_minus_sum_beta
+  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval,betaval,gammaval
+
+  ! array with the local to global mapping per slice
+  logical, dimension(NSPEC_CRUST_MANTLE) :: ispec_is_tiso
+
+  ! gravity
+  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table,density_table,minus_deriv_gravity_table
+
+! local parameters
+  ! Deville
+  ! manually inline the calls to the Deville et al. (2002) routines
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: &
+    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: dummyx_loc,dummyy_loc,dummyz_loc, &
+    newtempx1,newtempx2,newtempx3,newtempy1,newtempy2,newtempy3,newtempz1,newtempz2,newtempz3
+  real(kind=CUSTOM_REAL), dimension(NGLLX,m2) :: B1_m1_m2_5points,B2_m1_m2_5points,B3_m1_m2_5points
+  real(kind=CUSTOM_REAL), dimension(m1,m2) :: C1_m1_m2_5points,C2_m1_m2_5points,C3_m1_m2_5points
+  real(kind=CUSTOM_REAL), dimension(m1,m2) :: E1_m1_m2_5points,E2_m1_m2_5points,E3_m1_m2_5points
+
+  equivalence(dummyx_loc,B1_m1_m2_5points)
+  equivalence(dummyy_loc,B2_m1_m2_5points)
+  equivalence(dummyz_loc,B3_m1_m2_5points)
+  equivalence(tempx1,C1_m1_m2_5points)
+  equivalence(tempy1,C2_m1_m2_5points)
+  equivalence(tempz1,C3_m1_m2_5points)
+  equivalence(newtempx1,E1_m1_m2_5points)
+  equivalence(newtempy1,E2_m1_m2_5points)
+  equivalence(newtempz1,E3_m1_m2_5points)
+
+  real(kind=CUSTOM_REAL), dimension(m2,NGLLX) :: &
+    A1_mxm_m2_m1_5points,A2_mxm_m2_m1_5points,A3_mxm_m2_m1_5points
+  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
+    C1_mxm_m2_m1_5points,C2_mxm_m2_m1_5points,C3_mxm_m2_m1_5points
+  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
+    E1_mxm_m2_m1_5points,E2_mxm_m2_m1_5points,E3_mxm_m2_m1_5points
+
+  equivalence(dummyx_loc,A1_mxm_m2_m1_5points)
+  equivalence(dummyy_loc,A2_mxm_m2_m1_5points)
+  equivalence(dummyz_loc,A3_mxm_m2_m1_5points)
+  equivalence(tempx3,C1_mxm_m2_m1_5points)
+  equivalence(tempy3,C2_mxm_m2_m1_5points)
+  equivalence(tempz3,C3_mxm_m2_m1_5points)
+  equivalence(newtempx3,E1_mxm_m2_m1_5points)
+  equivalence(newtempy3,E2_mxm_m2_m1_5points)
+  equivalence(newtempz3,E3_mxm_m2_m1_5points)
+
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: sum_terms
+
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc  
+  real(kind=CUSTOM_REAL) fac1,fac2,fac3 
+
+  ! for gravity
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: rho_s_H
+
+  integer :: ispec
+  integer :: i,j,k
+  integer :: iglob1
+
+
+! this for non blocking MPI
+  integer :: iphase,icall
+
+  integer :: computed_elements
+
+  logical, dimension(NSPEC_CRUST_MANTLE) :: is_on_a_slice_edge_crust_mantle
+
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: accel_inner_core
+
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool_inner_core
+
+  integer, dimension(NSPEC_INNER_CORE) :: idoubling_inner_core
+
+  integer :: ichunk,iproc_xi,iproc_eta,myrank
+
+  integer, dimension(NCHUNKS_VAL,0:NPROC_XI_VAL-1,0:NPROC_ETA_VAL-1) :: addressing
+
+  integer, dimension(NGLOB2DMAX_XMIN_XMAX_CM) :: iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle
+  integer, dimension(NGLOB2DMAX_YMIN_YMAX_CM) :: iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle
+
+  integer, dimension(NGLOB2DMAX_XMIN_XMAX_IC) :: iboolleft_xi_inner_core,iboolright_xi_inner_core
+  integer, dimension(NGLOB2DMAX_YMIN_YMAX_IC) :: iboolleft_eta_inner_core,iboolright_eta_inner_core
+
+  integer npoin2D_faces_crust_mantle(NUMFACES_SHARED)
+  integer npoin2D_faces_inner_core(NUMFACES_SHARED)
+
+  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+       npoin2D_xi_inner_core,npoin2D_eta_inner_core
+
+! communication pattern for faces between chunks
+  integer, dimension(NUMMSGS_FACES_VAL) :: iprocfrom_faces,iprocto_faces
+
+! communication pattern for corners between chunks
+  integer, dimension(NCORNERSCHUNKS_VAL) :: iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners
+
+  integer, dimension(NGLOB1D_RADIAL_CM,NUMCORNERS_SHARED) :: iboolcorner_crust_mantle
+  integer, dimension(NGLOB1D_RADIAL_IC,NUMCORNERS_SHARED) :: iboolcorner_inner_core
+
+  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_crust_mantle
+  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_inner_core
+
+  integer :: npoin2D_max_all_CM_IC
+  real(kind=CUSTOM_REAL), dimension(NDIM,npoin2D_max_all_CM_IC) :: buffer_send_faces,buffer_received_faces
+
+! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB1D_RADIAL_CM + NGLOB1D_RADIAL_IC) :: &
+     buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector
+
+! for matching with central cube in inner core
+  integer nb_msgs_theor_in_cube, npoin2D_cube_from_slices,iphase_CC
+  integer, dimension(nb_msgs_theor_in_cube) :: sender_from_slices_to_cube
+  double precision, dimension(npoin2D_cube_from_slices,NDIM) :: buffer_slices
+  double precision, dimension(npoin2D_cube_from_slices,NDIM,nb_msgs_theor_in_cube) :: buffer_all_cube_from_slices
+  integer, dimension(nb_msgs_theor_in_cube,npoin2D_cube_from_slices):: ibool_central_cube
+  integer receiver_cube_from_slices
+  logical :: INCLUDE_CENTRAL_CUBE
+
+! local to global mapping
+  integer NSPEC2D_BOTTOM_INNER_CORE
+  integer, dimension(NSPEC2D_BOTTOM_INNER_CORE) :: ibelm_bottom_inner_core
+
+#ifdef _HANDOPT
+  integer, dimension(5) :: iglobv5
+#endif
+
+! ****************************************************
+!   big loop over all spectral elements in the solid
+! ****************************************************
+
+  computed_elements = 0
+
+  do ispec = 1,NSPEC_CRUST_MANTLE
+
+! hide communications by computing the edges first
+    if((icall == 2 .and. is_on_a_slice_edge_crust_mantle(ispec)) .or. &
+       (icall == 1 .and. .not. is_on_a_slice_edge_crust_mantle(ispec))) cycle
+
+! process the communications every ELEMENTS_NONBLOCKING elements
+    computed_elements = computed_elements + 1
+    if (USE_NONBLOCKING_COMMS .and. icall == 2 .and. mod(computed_elements,ELEMENTS_NONBLOCKING_CM_IC) == 0) then
+
+      if(iphase <= 7) call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES_VAL,NCORNERSCHUNKS_VAL, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL_CM, &
+            NGLOB1D_RADIAL_IC,NCHUNKS_VAL,iphase)
+
+      if(INCLUDE_CENTRAL_CUBE) then
+          if(iphase > 7 .and. iphase_CC <= 4) &
+            call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+                   npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+                   receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
+                   ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,accel_inner_core,NDIM,iphase_CC)
+      endif
+
+    endif
+
+    ! subroutines adapted from Deville, Fischer and Mund, High-order methods
+    ! for incompressible fluid flow, Cambridge University Press (2002),
+    ! pages 386 and 389 and Figure 8.3.1
+    do k=1,NGLLZ
+      do j=1,NGLLY
+
+#ifdef _HANDOPT
+! way 2:
+        ! since we know that NGLLX = 5, this should help pipelining
+        iglobv5(:) = ibool(:,j,k,ispec)
+        
+        dummyx_loc(1,j,k) = displ_crust_mantle(1,iglobv5(1))
+        dummyy_loc(1,j,k) = displ_crust_mantle(2,iglobv5(1))
+        dummyz_loc(1,j,k) = displ_crust_mantle(3,iglobv5(1))
+
+        dummyx_loc(2,j,k) = displ_crust_mantle(1,iglobv5(2))
+        dummyy_loc(2,j,k) = displ_crust_mantle(2,iglobv5(2))
+        dummyz_loc(2,j,k) = displ_crust_mantle(3,iglobv5(2))
+
+        dummyx_loc(3,j,k) = displ_crust_mantle(1,iglobv5(3))
+        dummyy_loc(3,j,k) = displ_crust_mantle(2,iglobv5(3))
+        dummyz_loc(3,j,k) = displ_crust_mantle(3,iglobv5(3))
+
+        dummyx_loc(4,j,k) = displ_crust_mantle(1,iglobv5(4))
+        dummyy_loc(4,j,k) = displ_crust_mantle(2,iglobv5(4))
+        dummyz_loc(4,j,k) = displ_crust_mantle(3,iglobv5(4))
+
+        dummyx_loc(5,j,k) = displ_crust_mantle(1,iglobv5(5))
+        dummyy_loc(5,j,k) = displ_crust_mantle(2,iglobv5(5))
+        dummyz_loc(5,j,k) = displ_crust_mantle(3,iglobv5(5))
+        
+#else
+! way 1:
+        do i=1,NGLLX
+            iglob1 = ibool(i,j,k,ispec)
+            dummyx_loc(i,j,k) = displ_crust_mantle(1,iglob1)
+            dummyy_loc(i,j,k) = displ_crust_mantle(2,iglob1)
+            dummyz_loc(i,j,k) = displ_crust_mantle(3,iglob1)
+        enddo
+#endif
+      enddo
+    enddo
+    do j=1,m2
+      do i=1,m1
+        C1_m1_m2_5points(i,j) = hprime_xx(i,1)*B1_m1_m2_5points(1,j) + &
+                              hprime_xx(i,2)*B1_m1_m2_5points(2,j) + &
+                              hprime_xx(i,3)*B1_m1_m2_5points(3,j) + &
+                              hprime_xx(i,4)*B1_m1_m2_5points(4,j) + &
+                              hprime_xx(i,5)*B1_m1_m2_5points(5,j)
+
+        C2_m1_m2_5points(i,j) = hprime_xx(i,1)*B2_m1_m2_5points(1,j) + &
+                              hprime_xx(i,2)*B2_m1_m2_5points(2,j) + &
+                              hprime_xx(i,3)*B2_m1_m2_5points(3,j) + &
+                              hprime_xx(i,4)*B2_m1_m2_5points(4,j) + &
+                              hprime_xx(i,5)*B2_m1_m2_5points(5,j)
+
+        C3_m1_m2_5points(i,j) = hprime_xx(i,1)*B3_m1_m2_5points(1,j) + &
+                              hprime_xx(i,2)*B3_m1_m2_5points(2,j) + &
+                              hprime_xx(i,3)*B3_m1_m2_5points(3,j) + &
+                              hprime_xx(i,4)*B3_m1_m2_5points(4,j) + &
+                              hprime_xx(i,5)*B3_m1_m2_5points(5,j)
+      enddo
+    enddo
+    do j=1,m1
+      do i=1,m1
+        ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
+        do k = 1,NGLLX
+          tempx2(i,j,k) = dummyx_loc(i,1,k)*hprime_xxT(1,j) + &
+                        dummyx_loc(i,2,k)*hprime_xxT(2,j) + &
+                        dummyx_loc(i,3,k)*hprime_xxT(3,j) + &
+                        dummyx_loc(i,4,k)*hprime_xxT(4,j) + &
+                        dummyx_loc(i,5,k)*hprime_xxT(5,j)
+
+          tempy2(i,j,k) = dummyy_loc(i,1,k)*hprime_xxT(1,j) + &
+                        dummyy_loc(i,2,k)*hprime_xxT(2,j) + &
+                        dummyy_loc(i,3,k)*hprime_xxT(3,j) + &
+                        dummyy_loc(i,4,k)*hprime_xxT(4,j) + &
+                        dummyy_loc(i,5,k)*hprime_xxT(5,j)
+
+          tempz2(i,j,k) = dummyz_loc(i,1,k)*hprime_xxT(1,j) + &
+                        dummyz_loc(i,2,k)*hprime_xxT(2,j) + &
+                        dummyz_loc(i,3,k)*hprime_xxT(3,j) + &
+                        dummyz_loc(i,4,k)*hprime_xxT(4,j) + &
+                        dummyz_loc(i,5,k)*hprime_xxT(5,j)
+        enddo
+      enddo
+    enddo
+    do j=1,m1
+      do i=1,m2
+        C1_mxm_m2_m1_5points(i,j) = A1_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
+                                  A1_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
+                                  A1_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
+                                  A1_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
+                                  A1_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
+
+        C2_mxm_m2_m1_5points(i,j) = A2_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
+                                  A2_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
+                                  A2_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
+                                  A2_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
+                                  A2_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
+
+        C3_mxm_m2_m1_5points(i,j) = A3_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
+                                  A3_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
+                                  A3_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
+                                  A3_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
+                                  A3_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
+      enddo
+    enddo
+
+    !
+    ! compute either isotropic, transverse isotropic or anisotropic elements
+    !
+    if(ANISOTROPIC_3D_MANTLE_VAL) then
+      ! anisotropic element
+      call compute_element_aniso(ispec, &
+                    minus_gravity_table,density_table,minus_deriv_gravity_table, &
+                    xstore,ystore,zstore, &
+                    xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+                    wgll_cube, &
+                    c11store,c12store,c13store,c14store,c15store,c16store,c22store, &
+                    c23store,c24store,c25store,c26store,c33store,c34store,c35store, &
+                    c36store,c44store,c45store,c46store,c55store,c56store,c66store, &
+                    ibool, &
+                    R_memory,epsilon_trace_over_3, &
+                    one_minus_sum_beta,vx,vy,vz,vnspec, &
+                    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3, &
+                    dummyx_loc,dummyy_loc,dummyz_loc,epsilondev_loc,rho_s_H)    
+    else 
+      if( .not. ispec_is_tiso(ispec) ) then
+        ! isotropic element
+        call compute_element_iso(ispec, &
+                    minus_gravity_table,density_table,minus_deriv_gravity_table, &
+                    xstore,ystore,zstore, &          
+                    xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+                    wgll_cube, &
+                    kappavstore,muvstore, &
+                    ibool, &
+                    R_memory,epsilon_trace_over_3, &
+                    one_minus_sum_beta,vx,vy,vz,vnspec, &          
+                    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3, &
+                    dummyx_loc,dummyy_loc,dummyz_loc,epsilondev_loc,rho_s_H) 
+      else      
+        ! transverse isotropic element
+        call compute_element_tiso(ispec, &
+                    minus_gravity_table,density_table,minus_deriv_gravity_table, &
+                    xstore,ystore,zstore, &
+                    xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+                    wgll_cube, &
+                    kappavstore,kappahstore,muvstore,muhstore,eta_anisostore, &
+                    ibool, &
+                    R_memory,epsilon_trace_over_3, &
+                    one_minus_sum_beta,vx,vy,vz,vnspec, &
+                    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3, &
+                    dummyx_loc,dummyy_loc,dummyz_loc,epsilondev_loc,rho_s_H)                
+      endif ! .not. ispec_is_tiso      
+    endif 
+            
+    ! subroutines adapted from Deville, Fischer and Mund, High-order methods
+    ! for incompressible fluid flow, Cambridge University Press (2002),
+    ! pages 386 and 389 and Figure 8.3.1
+    do j=1,m2
+      do i=1,m1
+        E1_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C1_m1_m2_5points(1,j) + &
+                              hprimewgll_xxT(i,2)*C1_m1_m2_5points(2,j) + &
+                              hprimewgll_xxT(i,3)*C1_m1_m2_5points(3,j) + &
+                              hprimewgll_xxT(i,4)*C1_m1_m2_5points(4,j) + &
+                              hprimewgll_xxT(i,5)*C1_m1_m2_5points(5,j)
+
+        E2_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C2_m1_m2_5points(1,j) + &
+                              hprimewgll_xxT(i,2)*C2_m1_m2_5points(2,j) + &
+                              hprimewgll_xxT(i,3)*C2_m1_m2_5points(3,j) + &
+                              hprimewgll_xxT(i,4)*C2_m1_m2_5points(4,j) + &
+                              hprimewgll_xxT(i,5)*C2_m1_m2_5points(5,j)
+
+        E3_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C3_m1_m2_5points(1,j) + &
+                              hprimewgll_xxT(i,2)*C3_m1_m2_5points(2,j) + &
+                              hprimewgll_xxT(i,3)*C3_m1_m2_5points(3,j) + &
+                              hprimewgll_xxT(i,4)*C3_m1_m2_5points(4,j) + &
+                              hprimewgll_xxT(i,5)*C3_m1_m2_5points(5,j)
+      enddo
+    enddo
+    do i=1,m1
+      do j=1,m1
+        ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
+        do k = 1,NGLLX
+          newtempx2(i,j,k) = tempx2(i,1,k)*hprimewgll_xx(1,j) + &
+                           tempx2(i,2,k)*hprimewgll_xx(2,j) + &
+                           tempx2(i,3,k)*hprimewgll_xx(3,j) + &
+                           tempx2(i,4,k)*hprimewgll_xx(4,j) + &
+                           tempx2(i,5,k)*hprimewgll_xx(5,j)
+
+          newtempy2(i,j,k) = tempy2(i,1,k)*hprimewgll_xx(1,j) + &
+                           tempy2(i,2,k)*hprimewgll_xx(2,j) + &
+                           tempy2(i,3,k)*hprimewgll_xx(3,j) + &
+                           tempy2(i,4,k)*hprimewgll_xx(4,j) + &
+                           tempy2(i,5,k)*hprimewgll_xx(5,j)
+
+          newtempz2(i,j,k) = tempz2(i,1,k)*hprimewgll_xx(1,j) + &
+                           tempz2(i,2,k)*hprimewgll_xx(2,j) + &
+                           tempz2(i,3,k)*hprimewgll_xx(3,j) + &
+                           tempz2(i,4,k)*hprimewgll_xx(4,j) + &
+                           tempz2(i,5,k)*hprimewgll_xx(5,j)
+        enddo
+      enddo
+    enddo
+    do j=1,m1
+      do i=1,m2
+        E1_mxm_m2_m1_5points(i,j) = C1_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
+                                  C1_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
+                                  C1_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
+                                  C1_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
+                                  C1_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
+
+        E2_mxm_m2_m1_5points(i,j) = C2_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
+                                  C2_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
+                                  C2_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
+                                  C2_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
+                                  C2_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
+
+        E3_mxm_m2_m1_5points(i,j) = C3_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
+                                  C3_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
+                                  C3_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
+                                  C3_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
+                                  C3_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
+      enddo
+    enddo
+
+    do k=1,NGLLZ
+      do j=1,NGLLY
+        fac1 = wgllwgll_yz(j,k)
+        do i=1,NGLLX
+          fac2 = wgllwgll_xz(i,k)
+          fac3 = wgllwgll_xy(i,j)
+
+          ! sum contributions
+          sum_terms(1,i,j,k) = - (fac1*newtempx1(i,j,k) + fac2*newtempx2(i,j,k) + fac3*newtempx3(i,j,k))
+          sum_terms(2,i,j,k) = - (fac1*newtempy1(i,j,k) + fac2*newtempy2(i,j,k) + fac3*newtempy3(i,j,k))
+          sum_terms(3,i,j,k) = - (fac1*newtempz1(i,j,k) + fac2*newtempz2(i,j,k) + fac3*newtempz3(i,j,k))
+
+          if(GRAVITY_VAL) sum_terms(:,i,j,k) = sum_terms(:,i,j,k) + rho_s_H(:,i,j,k) 
+
+        enddo ! NGLLX
+
+      enddo ! NGLLY
+    enddo ! NGLLZ
+
+    ! sum contributions from each element to the global mesh and add gravity terms
+    do k=1,NGLLZ
+      do j=1,NGLLY
+
+#ifdef _HANDOPT
+! way 2: 
+        iglobv5(:) = ibool(:,j,k,ispec)
+
+        accel_crust_mantle(:,iglobv5(1)) = accel_crust_mantle(:,iglobv5(1)) + sum_terms(:,1,j,k)
+        accel_crust_mantle(:,iglobv5(2)) = accel_crust_mantle(:,iglobv5(2)) + sum_terms(:,2,j,k)
+        accel_crust_mantle(:,iglobv5(3)) = accel_crust_mantle(:,iglobv5(3)) + sum_terms(:,3,j,k)
+        accel_crust_mantle(:,iglobv5(4)) = accel_crust_mantle(:,iglobv5(4)) + sum_terms(:,4,j,k)
+        accel_crust_mantle(:,iglobv5(5)) = accel_crust_mantle(:,iglobv5(5)) + sum_terms(:,5,j,k)
+        
+#else      
+! way 1:
+        do i=1,NGLLX
+          iglob1 = ibool(i,j,k,ispec)
+          accel_crust_mantle(:,iglob1) = accel_crust_mantle(:,iglob1) + sum_terms(:,i,j,k)
+        enddo
+#endif
+      enddo
+    enddo
+
+    ! update memory variables based upon the Runge-Kutta scheme
+    ! convention for attenuation
+    ! term in xx = 1
+    ! term in yy = 2
+    ! term in xy = 3
+    ! term in xz = 4
+    ! term in yz = 5
+    ! term in zz not computed since zero trace
+    ! This is because we only implement Q_\mu attenuation and not Q_\kappa.
+    ! Note that this does *NOT* imply that there is no attenuation for P waves
+    ! because for Q_\kappa = infinity one gets (see for instance Dahlen and Tromp (1998)
+    ! equation (9.59) page 350): Q_\alpha = Q_\mu * 3 * (V_p/V_s)^2 / 4
+    ! therefore Q_\alpha is not zero; for instance for V_p / V_s = sqrt(3)
+    ! we get Q_\alpha = (9 / 4) * Q_\mu = 2.25 * Q_\mu
+
+    if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. ) ) then
+
+      ! updates R_memory
+      call compute_element_att_memory_cr(ispec,R_memory, &
+                                      vx,vy,vz,vnspec,factor_common, &
+                                      alphaval,betaval,gammaval, &
+                                      c44store,muvstore, &
+                                      epsilondev,epsilondev_loc)
+          
+    endif
+
+    ! save deviatoric strain for Runge-Kutta scheme
+    if(COMPUTE_AND_STORE_STRAIN) then
+      epsilondev(:,:,:,:,ispec) = epsilondev_loc(:,:,:,:)
+    endif
+
+  enddo   ! spectral element loop NSPEC_CRUST_MANTLE
+
+  end subroutine compute_forces_crust_mantle_Dev
+

Deleted: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_crust_mantle_Dev.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -1,1159 +0,0 @@
-!=====================================================================
-!
-!          S p e c f e m 3 D  G l o b e  V e r s i o n  5 . 1
-!          --------------------------------------------------
-!
-!          Main authors: Dimitri Komatitsch and Jeroen Tromp
-!                        Princeton University, USA
-!             and University of Pau / CNRS / INRIA, France
-! (c) Princeton University / California Institute of Technology and University of Pau / CNRS / INRIA
-!                            April 2011
-!
-! This program is free software; you can redistribute it and/or modify
-! it under the terms of the GNU General Public License as published by
-! the Free Software Foundation; either version 2 of the License, or
-! (at your option) any later version.
-!
-! This program is distributed in the hope that it will be useful,
-! but WITHOUT ANY WARRANTY; without even the implied warranty of
-! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-! GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along
-! with this program; if not, write to the Free Software Foundation, Inc.,
-! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-!
-!=====================================================================
-
-  subroutine compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_crust_mantle,accel_crust_mantle,xstore,ystore,zstore, &
-          xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,icall, &
-            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_INNER_CORE,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT, &
-          hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore,kappahstore,muvstore,muhstore,eta_anisostore, &
-          c11store,c12store,c13store,c14store,c15store,c16store,c22store, &
-          c23store,c24store,c25store,c26store,c33store,c34store,c35store, &
-          c36store,c44store,c45store,c46store,c55store,c56store,c66store, &
-          ibool,ispec_is_tiso, &
-        ! --idoubling,
-          R_memory,epsilondev,epsilon_trace_over_3,one_minus_sum_beta, &
-          alphaval,betaval,gammaval,factor_common,vx,vy,vz,vnspec)
-
-! this routine is optimized for NGLLX = NGLLY = NGLLZ = 5 using the Deville et al. (2002) inlined matrix-matrix products
-
-  implicit none
-
-  include "constants.h"
-
-  ! include values created by the mesher
-  ! done for performance only using static allocation to allow for loop unrolling
-  include "OUTPUT_FILES/values_from_mesher.h"
-
-  ! displacement and acceleration
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: displ_crust_mantle,accel_crust_mantle
-  ! arrays with mesh parameters per slice
-  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool
-
-  ! x y and z contain r theta and phi
-  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: xstore,ystore,zstore
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: &
-        xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz
-
-  ! array with derivatives of Lagrange polynomials and precalculated products
-  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xx,hprimewgll_xx
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xxT,hprimewgll_xxT
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY) :: wgllwgll_xy
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ) :: wgllwgll_xz
-  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ) :: wgllwgll_yz
-
-  ! store anisotropic properties only where needed to save memory
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_TISO_MANTLE) :: &
-        kappahstore,muhstore,eta_anisostore
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ISO_MANTLE) :: &
-        kappavstore,muvstore
-
-  ! arrays for full anisotropy only when needed
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_MANTLE) :: &
-        c11store,c12store,c13store,c14store,c15store,c16store,c22store, &
-        c23store,c24store,c25store,c26store,c33store,c34store,c35store, &
-        c36store,c44store,c45store,c46store,c55store,c56store,c66store
-
-  ! attenuation
-  ! memory variables for attenuation
-  ! memory variables R_ij are stored at the local rather than global level
-  ! to allow for optimization of cache access by compiler
-  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilondev
-  real(kind=CUSTOM_REAL),dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilon_trace_over_3
-
-  integer vx,vy,vz,vnspec
-
-  ! [alpha,beta,gamma]val reduced to N_SLS and factor_common to N_SLS*NUM_NODES
-  real(kind=CUSTOM_REAL), dimension(N_SLS, vx, vy, vz, vnspec) :: factor_common
-  real(kind=CUSTOM_REAL), dimension(vx, vy, vz, vnspec) :: one_minus_sum_beta
-  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval,betaval,gammaval
-
-  ! array with the local to global mapping per slice
-!  integer, dimension(NSPEC_CRUST_MANTLE) :: idoubling
-  logical, dimension(NSPEC_CRUST_MANTLE) :: ispec_is_tiso
-
-  ! gravity
-  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table,density_table,minus_deriv_gravity_table
-
-! local parameters
-  ! Deville
-  ! manually inline the calls to the Deville et al. (2002) routines
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: &
-    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: dummyx_loc,dummyy_loc,dummyz_loc, &
-    newtempx1,newtempx2,newtempx3,newtempy1,newtempy2,newtempy3,newtempz1,newtempz2,newtempz3
-  real(kind=CUSTOM_REAL), dimension(NGLLX,m2) :: B1_m1_m2_5points,B2_m1_m2_5points,B3_m1_m2_5points
-  real(kind=CUSTOM_REAL), dimension(m1,m2) :: C1_m1_m2_5points,C2_m1_m2_5points,C3_m1_m2_5points
-  real(kind=CUSTOM_REAL), dimension(m1,m2) :: E1_m1_m2_5points,E2_m1_m2_5points,E3_m1_m2_5points
-
-  equivalence(dummyx_loc,B1_m1_m2_5points)
-  equivalence(dummyy_loc,B2_m1_m2_5points)
-  equivalence(dummyz_loc,B3_m1_m2_5points)
-  equivalence(tempx1,C1_m1_m2_5points)
-  equivalence(tempy1,C2_m1_m2_5points)
-  equivalence(tempz1,C3_m1_m2_5points)
-  equivalence(newtempx1,E1_m1_m2_5points)
-  equivalence(newtempy1,E2_m1_m2_5points)
-  equivalence(newtempz1,E3_m1_m2_5points)
-
-  real(kind=CUSTOM_REAL), dimension(m2,NGLLX) :: &
-    A1_mxm_m2_m1_5points,A2_mxm_m2_m1_5points,A3_mxm_m2_m1_5points
-  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
-    C1_mxm_m2_m1_5points,C2_mxm_m2_m1_5points,C3_mxm_m2_m1_5points
-  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
-    E1_mxm_m2_m1_5points,E2_mxm_m2_m1_5points,E3_mxm_m2_m1_5points
-
-  equivalence(dummyx_loc,A1_mxm_m2_m1_5points)
-  equivalence(dummyy_loc,A2_mxm_m2_m1_5points)
-  equivalence(dummyz_loc,A3_mxm_m2_m1_5points)
-  equivalence(tempx3,C1_mxm_m2_m1_5points)
-  equivalence(tempy3,C2_mxm_m2_m1_5points)
-  equivalence(tempz3,C3_mxm_m2_m1_5points)
-  equivalence(newtempx3,E1_mxm_m2_m1_5points)
-  equivalence(newtempy3,E2_mxm_m2_m1_5points)
-  equivalence(newtempz3,E3_mxm_m2_m1_5points)
-
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: sum_terms
-
-  ! for attenuation
-  real(kind=CUSTOM_REAL), dimension(NGLLX, NGLLY, NGLLZ) :: &
-    factor_common_c44_muv
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
-  real(kind=CUSTOM_REAL) R_xx_val1,R_yy_val1,R_xx_val2,R_yy_val2,R_xx_val3,R_yy_val3
-  real(kind=CUSTOM_REAL) one_minus_sum_beta_use,minus_sum_beta
-
-  ! the 21 coefficients for an anisotropic medium in reduced notation
-  real(kind=CUSTOM_REAL) c11,c22,c33,c44,c55,c66,c12,c13,c23,c14,c24,c34,c15,c25,c35,c45,c16,c26,c36,c46,c56
-
-  real(kind=CUSTOM_REAL) rhovphsq,sinphifour,cosphisq,sinphisq,costhetasq,rhovsvsq,sinthetasq, &
-        cosphifour,costhetafour,rhovpvsq,sinthetafour,rhovshsq,cosfourphi, &
-        costwotheta,cosfourtheta,sintwophisq,costheta,sinphi,sintheta,cosphi, &
-        sintwotheta,costwophi,sintwophi,costwothetasq,costwophisq,phi,theta
-
-  real(kind=CUSTOM_REAL) two_rhovpvsq,two_rhovphsq,two_rhovsvsq,two_rhovshsq
-  real(kind=CUSTOM_REAL) four_rhovpvsq,four_rhovphsq,four_rhovsvsq,four_rhovshsq
-
-  real(kind=CUSTOM_REAL) twoetaminone,etaminone,eta_aniso
-  real(kind=CUSTOM_REAL) two_eta_aniso,four_eta_aniso,six_eta_aniso
-  real(kind=CUSTOM_REAL) xixl,xiyl,xizl,etaxl,etayl,etazl,gammaxl,gammayl,gammazl,jacobianl
-  real(kind=CUSTOM_REAL) duxdxl,duxdyl,duxdzl,duydxl,duydyl,duydzl,duzdxl,duzdyl,duzdzl
-  real(kind=CUSTOM_REAL) duxdxl_plus_duydyl,duxdxl_plus_duzdzl,duydyl_plus_duzdzl
-  real(kind=CUSTOM_REAL) duxdyl_plus_duydxl,duzdxl_plus_duxdzl,duzdyl_plus_duydzl
-  real(kind=CUSTOM_REAL) sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz
-
-  real(kind=CUSTOM_REAL) fac1,fac2,fac3,templ
-  real(kind=CUSTOM_REAL) lambdal,mul,lambdalplus2mul
-  real(kind=CUSTOM_REAL) kappal,kappavl,kappahl,muvl,muhl
-
-  ! for gravity
-  double precision radius,rho,minus_g,minus_dg
-  double precision minus_g_over_radius,minus_dg_plus_g_over_radius
-  double precision cos_theta,sin_theta,cos_phi,sin_phi
-  double precision cos_theta_sq,sin_theta_sq,cos_phi_sq,sin_phi_sq
-  double precision factor,sx_l,sy_l,sz_l,gxl,gyl,gzl
-  double precision Hxxl,Hyyl,Hzzl,Hxyl,Hxzl,Hyzl
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: rho_s_H
-  real(kind=CUSTOM_REAL) sigma_yx,sigma_zx,sigma_zy
-
-  integer :: i_SLS,i_memory,imodulo_N_SLS
-  integer :: ispec,ispec_strain
-  integer :: i,j,k
-  integer :: int_radius
-  integer :: iglob1,iglob2,iglob3,iglob4,iglob5
-
-! this for non blocking MPI
-  integer :: iphase,icall
-
-  integer :: computed_elements
-
-  logical, dimension(NSPEC_CRUST_MANTLE) :: is_on_a_slice_edge_crust_mantle
-
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: accel_inner_core
-
-  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool_inner_core
-
-  integer, dimension(NSPEC_INNER_CORE) :: idoubling_inner_core
-
-  integer :: ichunk,iproc_xi,iproc_eta,myrank
-
-  integer, dimension(NCHUNKS_VAL,0:NPROC_XI_VAL-1,0:NPROC_ETA_VAL-1) :: addressing
-
-  integer, dimension(NGLOB2DMAX_XMIN_XMAX_CM) :: iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle
-  integer, dimension(NGLOB2DMAX_YMIN_YMAX_CM) :: iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle
-
-  integer, dimension(NGLOB2DMAX_XMIN_XMAX_IC) :: iboolleft_xi_inner_core,iboolright_xi_inner_core
-  integer, dimension(NGLOB2DMAX_YMIN_YMAX_IC) :: iboolleft_eta_inner_core,iboolright_eta_inner_core
-
-  integer npoin2D_faces_crust_mantle(NUMFACES_SHARED)
-  integer npoin2D_faces_inner_core(NUMFACES_SHARED)
-
-  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-       npoin2D_xi_inner_core,npoin2D_eta_inner_core
-
-! communication pattern for faces between chunks
-  integer, dimension(NUMMSGS_FACES_VAL) :: iprocfrom_faces,iprocto_faces
-
-! communication pattern for corners between chunks
-  integer, dimension(NCORNERSCHUNKS_VAL) :: iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners
-
-  integer, dimension(NGLOB1D_RADIAL_CM,NUMCORNERS_SHARED) :: iboolcorner_crust_mantle
-  integer, dimension(NGLOB1D_RADIAL_IC,NUMCORNERS_SHARED) :: iboolcorner_inner_core
-
-  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_crust_mantle
-  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_inner_core
-
-  integer :: npoin2D_max_all_CM_IC
-  real(kind=CUSTOM_REAL), dimension(NDIM,npoin2D_max_all_CM_IC) :: buffer_send_faces,buffer_received_faces
-
-! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB1D_RADIAL_CM + NGLOB1D_RADIAL_IC) :: &
-     buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector
-
-! for matching with central cube in inner core
-  integer nb_msgs_theor_in_cube, npoin2D_cube_from_slices,iphase_CC
-  integer, dimension(nb_msgs_theor_in_cube) :: sender_from_slices_to_cube
-  double precision, dimension(npoin2D_cube_from_slices,NDIM) :: buffer_slices
-  double precision, dimension(npoin2D_cube_from_slices,NDIM,nb_msgs_theor_in_cube) :: buffer_all_cube_from_slices
-  integer, dimension(nb_msgs_theor_in_cube,npoin2D_cube_from_slices):: ibool_central_cube
-  integer receiver_cube_from_slices
-  logical :: INCLUDE_CENTRAL_CUBE
-
-! local to global mapping
-  integer NSPEC2D_BOTTOM_INNER_CORE
-  integer, dimension(NSPEC2D_BOTTOM_INNER_CORE) :: ibelm_bottom_inner_core
-
-! ****************************************************
-!   big loop over all spectral elements in the solid
-! ****************************************************
-
-  imodulo_N_SLS = mod(N_SLS,3)
-
-  computed_elements = 0
-
-  do ispec = 1,NSPEC_CRUST_MANTLE
-
-! hide communications by computing the edges first
-    if((icall == 2 .and. is_on_a_slice_edge_crust_mantle(ispec)) .or. &
-       (icall == 1 .and. .not. is_on_a_slice_edge_crust_mantle(ispec))) cycle
-
-! process the communications every ELEMENTS_NONBLOCKING elements
-    computed_elements = computed_elements + 1
-    if (USE_NONBLOCKING_COMMS .and. icall == 2 .and. mod(computed_elements,ELEMENTS_NONBLOCKING_CM_IC) == 0) then
-
-      if(iphase <= 7) call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES_VAL,NCORNERSCHUNKS_VAL, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL_CM, &
-            NGLOB1D_RADIAL_IC,NCHUNKS_VAL,iphase)
-
-      if(INCLUDE_CENTRAL_CUBE) then
-          if(iphase > 7 .and. iphase_CC <= 4) &
-            call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-                   npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-                   receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
-                   ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,accel_inner_core,NDIM,iphase_CC)
-      endif
-
-    endif
-
-    ! subroutines adapted from Deville, Fischer and Mund, High-order methods
-    ! for incompressible fluid flow, Cambridge University Press (2002),
-    ! pages 386 and 389 and Figure 8.3.1
-    do k=1,NGLLZ
-      do j=1,NGLLY
-
-! way 1:
-!        do i=1,NGLLX
-!            iglob = ibool(i,j,k,ispec)
-!            dummyx_loc(i,j,k) = displ_crust_mantle(1,iglob)
-!            dummyy_loc(i,j,k) = displ_crust_mantle(2,iglob)
-!            dummyz_loc(i,j,k) = displ_crust_mantle(3,iglob)
-!        enddo
-
-! way 2:
-        ! since we know that NGLLX = 5, this should help pipelining
-        iglob1 = ibool(1,j,k,ispec)
-        iglob2 = ibool(2,j,k,ispec)
-        iglob3 = ibool(3,j,k,ispec)
-        iglob4 = ibool(4,j,k,ispec)
-        iglob5 = ibool(5,j,k,ispec)
-
-        dummyx_loc(1,j,k) = displ_crust_mantle(1,iglob1)
-        dummyy_loc(1,j,k) = displ_crust_mantle(2,iglob1)
-        dummyz_loc(1,j,k) = displ_crust_mantle(3,iglob1)
-
-        dummyx_loc(2,j,k) = displ_crust_mantle(1,iglob2)
-        dummyy_loc(2,j,k) = displ_crust_mantle(2,iglob2)
-        dummyz_loc(2,j,k) = displ_crust_mantle(3,iglob2)
-
-        dummyx_loc(3,j,k) = displ_crust_mantle(1,iglob3)
-        dummyy_loc(3,j,k) = displ_crust_mantle(2,iglob3)
-        dummyz_loc(3,j,k) = displ_crust_mantle(3,iglob3)
-
-        dummyx_loc(4,j,k) = displ_crust_mantle(1,iglob4)
-        dummyy_loc(4,j,k) = displ_crust_mantle(2,iglob4)
-        dummyz_loc(4,j,k) = displ_crust_mantle(3,iglob4)
-
-        dummyx_loc(5,j,k) = displ_crust_mantle(1,iglob5)
-        dummyy_loc(5,j,k) = displ_crust_mantle(2,iglob5)
-        dummyz_loc(5,j,k) = displ_crust_mantle(3,iglob5)
-
-      enddo
-    enddo
-    do j=1,m2
-      do i=1,m1
-        C1_m1_m2_5points(i,j) = hprime_xx(i,1)*B1_m1_m2_5points(1,j) + &
-                              hprime_xx(i,2)*B1_m1_m2_5points(2,j) + &
-                              hprime_xx(i,3)*B1_m1_m2_5points(3,j) + &
-                              hprime_xx(i,4)*B1_m1_m2_5points(4,j) + &
-                              hprime_xx(i,5)*B1_m1_m2_5points(5,j)
-
-        C2_m1_m2_5points(i,j) = hprime_xx(i,1)*B2_m1_m2_5points(1,j) + &
-                              hprime_xx(i,2)*B2_m1_m2_5points(2,j) + &
-                              hprime_xx(i,3)*B2_m1_m2_5points(3,j) + &
-                              hprime_xx(i,4)*B2_m1_m2_5points(4,j) + &
-                              hprime_xx(i,5)*B2_m1_m2_5points(5,j)
-
-        C3_m1_m2_5points(i,j) = hprime_xx(i,1)*B3_m1_m2_5points(1,j) + &
-                              hprime_xx(i,2)*B3_m1_m2_5points(2,j) + &
-                              hprime_xx(i,3)*B3_m1_m2_5points(3,j) + &
-                              hprime_xx(i,4)*B3_m1_m2_5points(4,j) + &
-                              hprime_xx(i,5)*B3_m1_m2_5points(5,j)
-      enddo
-    enddo
-    do j=1,m1
-      do i=1,m1
-        ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
-        do k = 1,NGLLX
-          tempx2(i,j,k) = dummyx_loc(i,1,k)*hprime_xxT(1,j) + &
-                        dummyx_loc(i,2,k)*hprime_xxT(2,j) + &
-                        dummyx_loc(i,3,k)*hprime_xxT(3,j) + &
-                        dummyx_loc(i,4,k)*hprime_xxT(4,j) + &
-                        dummyx_loc(i,5,k)*hprime_xxT(5,j)
-
-          tempy2(i,j,k) = dummyy_loc(i,1,k)*hprime_xxT(1,j) + &
-                        dummyy_loc(i,2,k)*hprime_xxT(2,j) + &
-                        dummyy_loc(i,3,k)*hprime_xxT(3,j) + &
-                        dummyy_loc(i,4,k)*hprime_xxT(4,j) + &
-                        dummyy_loc(i,5,k)*hprime_xxT(5,j)
-
-          tempz2(i,j,k) = dummyz_loc(i,1,k)*hprime_xxT(1,j) + &
-                        dummyz_loc(i,2,k)*hprime_xxT(2,j) + &
-                        dummyz_loc(i,3,k)*hprime_xxT(3,j) + &
-                        dummyz_loc(i,4,k)*hprime_xxT(4,j) + &
-                        dummyz_loc(i,5,k)*hprime_xxT(5,j)
-        enddo
-      enddo
-    enddo
-    do j=1,m1
-      do i=1,m2
-        C1_mxm_m2_m1_5points(i,j) = A1_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
-                                  A1_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
-                                  A1_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
-                                  A1_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
-                                  A1_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
-
-        C2_mxm_m2_m1_5points(i,j) = A2_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
-                                  A2_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
-                                  A2_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
-                                  A2_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
-                                  A2_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
-
-        C3_mxm_m2_m1_5points(i,j) = A3_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
-                                  A3_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
-                                  A3_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
-                                  A3_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
-                                  A3_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
-      enddo
-    enddo
-
-    do k=1,NGLLZ
-      do j=1,NGLLY
-        do i=1,NGLLX
-          ! get derivatives of ux, uy and uz with respect to x, y and z
-          xixl = xix(i,j,k,ispec)
-          xiyl = xiy(i,j,k,ispec)
-          xizl = xiz(i,j,k,ispec)
-          etaxl = etax(i,j,k,ispec)
-          etayl = etay(i,j,k,ispec)
-          etazl = etaz(i,j,k,ispec)
-          gammaxl = gammax(i,j,k,ispec)
-          gammayl = gammay(i,j,k,ispec)
-          gammazl = gammaz(i,j,k,ispec)
-
-          ! compute the jacobian
-          jacobianl = 1._CUSTOM_REAL / (xixl*(etayl*gammazl-etazl*gammayl) &
-                        - xiyl*(etaxl*gammazl-etazl*gammaxl) &
-                        + xizl*(etaxl*gammayl-etayl*gammaxl))
-
-          duxdxl = xixl*tempx1(i,j,k) + etaxl*tempx2(i,j,k) + gammaxl*tempx3(i,j,k)
-          duxdyl = xiyl*tempx1(i,j,k) + etayl*tempx2(i,j,k) + gammayl*tempx3(i,j,k)
-          duxdzl = xizl*tempx1(i,j,k) + etazl*tempx2(i,j,k) + gammazl*tempx3(i,j,k)
-
-          duydxl = xixl*tempy1(i,j,k) + etaxl*tempy2(i,j,k) + gammaxl*tempy3(i,j,k)
-          duydyl = xiyl*tempy1(i,j,k) + etayl*tempy2(i,j,k) + gammayl*tempy3(i,j,k)
-          duydzl = xizl*tempy1(i,j,k) + etazl*tempy2(i,j,k) + gammazl*tempy3(i,j,k)
-
-          duzdxl = xixl*tempz1(i,j,k) + etaxl*tempz2(i,j,k) + gammaxl*tempz3(i,j,k)
-          duzdyl = xiyl*tempz1(i,j,k) + etayl*tempz2(i,j,k) + gammayl*tempz3(i,j,k)
-          duzdzl = xizl*tempz1(i,j,k) + etazl*tempz2(i,j,k) + gammazl*tempz3(i,j,k)
-
-          ! precompute some sums to save CPU time
-          duxdxl_plus_duydyl = duxdxl + duydyl
-          duxdxl_plus_duzdzl = duxdxl + duzdzl
-          duydyl_plus_duzdzl = duydyl + duzdzl
-          duxdyl_plus_duydxl = duxdyl + duydxl
-          duzdxl_plus_duxdzl = duzdxl + duxdzl
-          duzdyl_plus_duydzl = duzdyl + duydzl
-
-          ! compute deviatoric strain
-          if (COMPUTE_AND_STORE_STRAIN) then
-            if(NSPEC_CRUST_MANTLE_STRAIN_ONLY == 1) then
-              ispec_strain = 1
-            else
-              ispec_strain = ispec
-            endif
-            templ = ONE_THIRD * (duxdxl + duydyl + duzdzl)
-            epsilon_trace_over_3(i,j,k,ispec_strain) = templ
-            epsilondev_loc(1,i,j,k) = duxdxl - templ
-            epsilondev_loc(2,i,j,k) = duydyl - templ
-            epsilondev_loc(3,i,j,k) = 0.5 * duxdyl_plus_duydxl
-            epsilondev_loc(4,i,j,k) = 0.5 * duzdxl_plus_duxdzl
-            epsilondev_loc(5,i,j,k) = 0.5 * duzdyl_plus_duydzl
-          endif
-
-          ! precompute terms for attenuation if needed
-          if(ATTENUATION_VAL) then
-            one_minus_sum_beta_use = one_minus_sum_beta(i,j,k,ispec)
-            minus_sum_beta =  one_minus_sum_beta_use - 1.0
-          endif
-
-          !
-          ! compute either isotropic or anisotropic elements
-          !
-          if(ANISOTROPIC_3D_MANTLE_VAL) then
-
-            c11 = c11store(i,j,k,ispec)
-            c12 = c12store(i,j,k,ispec)
-            c13 = c13store(i,j,k,ispec)
-            c14 = c14store(i,j,k,ispec)
-            c15 = c15store(i,j,k,ispec)
-            c16 = c16store(i,j,k,ispec)
-            c22 = c22store(i,j,k,ispec)
-            c23 = c23store(i,j,k,ispec)
-            c24 = c24store(i,j,k,ispec)
-            c25 = c25store(i,j,k,ispec)
-            c26 = c26store(i,j,k,ispec)
-            c33 = c33store(i,j,k,ispec)
-            c34 = c34store(i,j,k,ispec)
-            c35 = c35store(i,j,k,ispec)
-            c36 = c36store(i,j,k,ispec)
-            c44 = c44store(i,j,k,ispec)
-            c45 = c45store(i,j,k,ispec)
-            c46 = c46store(i,j,k,ispec)
-            c55 = c55store(i,j,k,ispec)
-            c56 = c56store(i,j,k,ispec)
-            c66 = c66store(i,j,k,ispec)
-
-            if(ATTENUATION_VAL) then
-              mul = c44
-              c11 = c11 + FOUR_THIRDS * minus_sum_beta * mul
-              c12 = c12 - TWO_THIRDS * minus_sum_beta * mul
-              c13 = c13 - TWO_THIRDS * minus_sum_beta * mul
-              c22 = c22 + FOUR_THIRDS * minus_sum_beta * mul
-              c23 = c23 - TWO_THIRDS * minus_sum_beta * mul
-              c33 = c33 + FOUR_THIRDS * minus_sum_beta * mul
-              c44 = c44 + minus_sum_beta * mul
-              c55 = c55 + minus_sum_beta * mul
-              c66 = c66 + minus_sum_beta * mul
-            endif
-
-            sigma_xx = c11*duxdxl + c16*duxdyl_plus_duydxl + c12*duydyl + &
-                     c15*duzdxl_plus_duxdzl + c14*duzdyl_plus_duydzl + c13*duzdzl
-
-            sigma_yy = c12*duxdxl + c26*duxdyl_plus_duydxl + c22*duydyl + &
-                     c25*duzdxl_plus_duxdzl + c24*duzdyl_plus_duydzl + c23*duzdzl
-
-            sigma_zz = c13*duxdxl + c36*duxdyl_plus_duydxl + c23*duydyl + &
-                     c35*duzdxl_plus_duxdzl + c34*duzdyl_plus_duydzl + c33*duzdzl
-
-            sigma_xy = c16*duxdxl + c66*duxdyl_plus_duydxl + c26*duydyl + &
-                     c56*duzdxl_plus_duxdzl + c46*duzdyl_plus_duydzl + c36*duzdzl
-
-            sigma_xz = c15*duxdxl + c56*duxdyl_plus_duydxl + c25*duydyl + &
-                     c55*duzdxl_plus_duxdzl + c45*duzdyl_plus_duydzl + c35*duzdzl
-
-            sigma_yz = c14*duxdxl + c46*duxdyl_plus_duydxl + c24*duydyl + &
-                     c45*duzdxl_plus_duxdzl + c44*duzdyl_plus_duydzl + c34*duzdzl
-
-          else
-
-            ! do not use transverse isotropy except if element is between d220 and Moho
-!            if(.not. (TRANSVERSE_ISOTROPY_VAL .and. (idoubling(ispec)==IFLAG_220_80 &
-!                  .or. idoubling(ispec)==IFLAG_80_MOHO))) then
-            if( .not. ispec_is_tiso(ispec) ) then
-
-              ! layer with no transverse isotropy, use kappav and muv
-              kappal = kappavstore(i,j,k,ispec)
-              mul = muvstore(i,j,k,ispec)
-
-              ! use unrelaxed parameters if attenuation
-              if(ATTENUATION_VAL) mul = mul * one_minus_sum_beta_use
-
-              lambdalplus2mul = kappal + FOUR_THIRDS * mul
-              lambdal = lambdalplus2mul - 2.*mul
-
-              ! compute stress sigma
-              sigma_xx = lambdalplus2mul*duxdxl + lambdal*duydyl_plus_duzdzl
-              sigma_yy = lambdalplus2mul*duydyl + lambdal*duxdxl_plus_duzdzl
-              sigma_zz = lambdalplus2mul*duzdzl + lambdal*duxdxl_plus_duydyl
-
-              sigma_xy = mul*duxdyl_plus_duydxl
-              sigma_xz = mul*duzdxl_plus_duxdzl
-              sigma_yz = mul*duzdyl_plus_duydzl
-
-            else
-
-! note : mesh is built such that anisotropic elements are created first in anisotropic layers,
-!           thus they are listed first ( see in create_regions_mesh.f90: perm_layer() ordering )
-!           this is therefore still in bounds of 1:NSPECMAX_TISO_MANTLE even if NSPECMAX_TISO is less than NSPEC
-
-              ! uncomment to debug
-              !if ( ispec > NSPECMAX_TISO_MANTLE ) then
-              !  print*,'error tiso: ispec = ',ispec,'max = ',NSPECMAX_TISO_MANTLE
-              !  call exit_mpi(0,'error tiso ispec bounds')
-              !endif
-
-              ! use Kappa and mu from transversely isotropic model
-              kappavl = kappavstore(i,j,k,ispec)
-              muvl = muvstore(i,j,k,ispec)
-
-              kappahl = kappahstore(i,j,k,ispec)
-              muhl = muhstore(i,j,k,ispec)
-
-              ! use unrelaxed parameters if attenuation
-              ! eta does not need to be shifted since it is a ratio
-              if(ATTENUATION_VAL) then
-                muvl = muvl * one_minus_sum_beta_use
-                muhl = muhl * one_minus_sum_beta_use
-              endif
-
-              rhovpvsq = kappavl + FOUR_THIRDS * muvl  !!! that is C
-              rhovphsq = kappahl + FOUR_THIRDS * muhl  !!! that is A
-
-              rhovsvsq = muvl  !!! that is L
-              rhovshsq = muhl  !!! that is N
-
-              eta_aniso = eta_anisostore(i,j,k,ispec)  !!! that is  F / (A - 2 L)
-
-              ! use mesh coordinates to get theta and phi
-              ! ystore and zstore contain theta and phi
-
-              iglob1 = ibool(i,j,k,ispec)
-              theta = ystore(iglob1)
-              phi = zstore(iglob1)
-
-              costheta = cos(theta)
-              sintheta = sin(theta)
-              cosphi = cos(phi)
-              sinphi = sin(phi)
-
-              costhetasq = costheta * costheta
-              sinthetasq = sintheta * sintheta
-              cosphisq = cosphi * cosphi
-              sinphisq = sinphi * sinphi
-
-              costhetafour = costhetasq * costhetasq
-              sinthetafour = sinthetasq * sinthetasq
-              cosphifour = cosphisq * cosphisq
-              sinphifour = sinphisq * sinphisq
-
-              costwotheta = cos(2.*theta)
-              sintwotheta = sin(2.*theta)
-              costwophi = cos(2.*phi)
-              sintwophi = sin(2.*phi)
-
-              cosfourtheta = cos(4.*theta)
-              cosfourphi = cos(4.*phi)
-
-              costwothetasq = costwotheta * costwotheta
-
-              costwophisq = costwophi * costwophi
-              sintwophisq = sintwophi * sintwophi
-
-              etaminone = eta_aniso - 1.
-              twoetaminone = 2. * eta_aniso - 1.
-
-              ! precompute some products to reduce the CPU time
-              two_eta_aniso = 2.*eta_aniso
-              four_eta_aniso = 4.*eta_aniso
-              six_eta_aniso = 6.*eta_aniso
-
-              two_rhovpvsq = 2.*rhovpvsq
-              two_rhovphsq = 2.*rhovphsq
-              two_rhovsvsq = 2.*rhovsvsq
-              two_rhovshsq = 2.*rhovshsq
-
-              four_rhovpvsq = 4.*rhovpvsq
-              four_rhovphsq = 4.*rhovphsq
-              four_rhovsvsq = 4.*rhovsvsq
-              four_rhovshsq = 4.*rhovshsq
-
-              ! the 21 anisotropic coefficients computed using Mathematica
-
-              c11 = rhovphsq*sinphifour + 2.*cosphisq*sinphisq* &
-                  (rhovphsq*costhetasq + (eta_aniso*rhovphsq + two_rhovsvsq - two_eta_aniso*rhovsvsq)* &
-                  sinthetasq) + cosphifour* &
-                  (rhovphsq*costhetafour + 2.*(eta_aniso*rhovphsq + two_rhovsvsq - two_eta_aniso*rhovsvsq)* &
-                  costhetasq*sinthetasq + rhovpvsq*sinthetafour)
-
-              c12 = ((rhovphsq - two_rhovshsq)*(3. + cosfourphi)*costhetasq)/4. - &
-                  four_rhovshsq*cosphisq*costhetasq*sinphisq + &
-                  (rhovphsq*(11. + 4.*costwotheta + cosfourtheta)*sintwophisq)/32. + &
-                  eta_aniso*(rhovphsq - two_rhovsvsq)*(cosphifour + &
-                  2.*cosphisq*costhetasq*sinphisq + sinphifour)*sinthetasq + &
-                  rhovpvsq*cosphisq*sinphisq*sinthetafour - &
-                  rhovsvsq*sintwophisq*sinthetafour
-
-              c13 = (cosphisq*(rhovphsq + six_eta_aniso*rhovphsq + rhovpvsq - four_rhovsvsq - &
-                  12.*eta_aniso*rhovsvsq + (twoetaminone*rhovphsq - rhovpvsq + four_rhovsvsq - &
-                  four_eta_aniso*rhovsvsq)*cosfourtheta))/8. + &
-                  sinphisq*(eta_aniso*(rhovphsq - two_rhovsvsq)*costhetasq + &
-                  (rhovphsq - two_rhovshsq)*sinthetasq)
-
-              c14 = costheta*sinphi*((cosphisq* &
-                   (-rhovphsq + rhovpvsq + four_rhovshsq - four_rhovsvsq + &
-                    (-rhovphsq + two_eta_aniso*rhovphsq - rhovpvsq + four_rhovsvsq - &
-                    four_eta_aniso*rhovsvsq)*costwotheta))/2. + &
-                    (etaminone*rhovphsq + 2.*(rhovshsq - eta_aniso*rhovsvsq))*sinphisq)* sintheta
-
-              c15 = cosphi*costheta*((cosphisq* (-rhovphsq + rhovpvsq + &
-                    (twoetaminone*rhovphsq - rhovpvsq + four_rhovsvsq - four_eta_aniso*rhovsvsq)* &
-                    costwotheta))/2. + etaminone*(rhovphsq - two_rhovsvsq)*sinphisq)*sintheta
-
-              c16 = (cosphi*sinphi*(cosphisq* (-rhovphsq + rhovpvsq + &
-                    (-rhovphsq + two_eta_aniso*rhovphsq - rhovpvsq + four_rhovsvsq - &
-                    four_eta_aniso*rhovsvsq)*costwotheta) + &
-                    2.*etaminone*(rhovphsq - two_rhovsvsq)*sinphisq)*sinthetasq)/2.
-
-              c22 = rhovphsq*cosphifour + 2.*cosphisq*sinphisq* &
-                  (rhovphsq*costhetasq + (eta_aniso*rhovphsq + two_rhovsvsq - two_eta_aniso*rhovsvsq)* &
-                  sinthetasq) + sinphifour* &
-                  (rhovphsq*costhetafour + 2.*(eta_aniso*rhovphsq + two_rhovsvsq - two_eta_aniso*rhovsvsq)* &
-                  costhetasq*sinthetasq + rhovpvsq*sinthetafour)
-
-              c23 = ((rhovphsq + six_eta_aniso*rhovphsq + rhovpvsq - four_rhovsvsq - 12.*eta_aniso*rhovsvsq + &
-                   (twoetaminone*rhovphsq - rhovpvsq + four_rhovsvsq - four_eta_aniso*rhovsvsq)* &
-                    cosfourtheta)*sinphisq)/8. + &
-                    cosphisq*(eta_aniso*(rhovphsq - two_rhovsvsq)*costhetasq + &
-                    (rhovphsq - two_rhovshsq)*sinthetasq)
-
-              c24 = costheta*sinphi*(etaminone*(rhovphsq - two_rhovsvsq)*cosphisq + &
-                    ((-rhovphsq + rhovpvsq + (twoetaminone*rhovphsq - rhovpvsq + &
-                    four_rhovsvsq - four_eta_aniso*rhovsvsq)*costwotheta)*sinphisq)/2.)*sintheta
-
-              c25 = cosphi*costheta*((etaminone*rhovphsq + 2.*(rhovshsq - eta_aniso*rhovsvsq))* &
-                    cosphisq + ((-rhovphsq + rhovpvsq + four_rhovshsq - four_rhovsvsq + &
-                     (-rhovphsq + two_eta_aniso*rhovphsq - rhovpvsq + four_rhovsvsq - &
-                    four_eta_aniso*rhovsvsq)*costwotheta)*sinphisq)/2.)*sintheta
-
-              c26 = (cosphi*sinphi*(2.*etaminone*(rhovphsq - two_rhovsvsq)*cosphisq + &
-                      (-rhovphsq + rhovpvsq + (-rhovphsq + two_eta_aniso*rhovphsq - rhovpvsq + four_rhovsvsq - &
-                      four_eta_aniso*rhovsvsq)*costwotheta)*sinphisq)*sinthetasq)/2.
-
-              c33 = rhovpvsq*costhetafour + 2.*(eta_aniso*(rhovphsq - two_rhovsvsq) + two_rhovsvsq)* &
-                    costhetasq*sinthetasq + rhovphsq*sinthetafour
-
-              c34 = -((rhovphsq - rhovpvsq + (twoetaminone*rhovphsq - rhovpvsq + four_rhovsvsq &
-                       - four_eta_aniso*rhovsvsq)*costwotheta)*sinphi*sintwotheta)/4.
-
-              c35 = -(cosphi*(rhovphsq - rhovpvsq + &
-                    (twoetaminone*rhovphsq - rhovpvsq + four_rhovsvsq - four_eta_aniso*rhovsvsq)* &
-                    costwotheta)*sintwotheta)/4.
-
-              c36 = -((rhovphsq - rhovpvsq - four_rhovshsq + four_rhovsvsq + &
-                    (twoetaminone*rhovphsq - rhovpvsq + four_rhovsvsq - four_eta_aniso*rhovsvsq)* &
-                    costwotheta)*sintwophi*sinthetasq)/4.
-
-              c44 = cosphisq*(rhovsvsq*costhetasq + rhovshsq*sinthetasq) + &
-                    sinphisq*(rhovsvsq*costwothetasq + &
-                    (rhovphsq - two_eta_aniso*rhovphsq + rhovpvsq + four_eta_aniso*rhovsvsq)*costhetasq* sinthetasq)
-
-              c45 = ((rhovphsq - two_eta_aniso*rhovphsq + rhovpvsq - two_rhovshsq - two_rhovsvsq + &
-                    four_eta_aniso*rhovsvsq + (rhovphsq - two_eta_aniso*rhovphsq + rhovpvsq + &
-                    4.*etaminone*rhovsvsq)*costwotheta)*sintwophi*sinthetasq)/4.
-
-              c46 = -(cosphi*costheta*((rhovshsq - rhovsvsq)*cosphisq - &
-                      ((rhovphsq - two_eta_aniso*rhovphsq + rhovpvsq - two_rhovshsq - two_rhovsvsq + &
-                      four_eta_aniso*rhovsvsq + (-rhovphsq + two_eta_aniso*rhovphsq - rhovpvsq + &
-                      four_rhovsvsq - four_eta_aniso*rhovsvsq)*costwotheta)*sinphisq)/2.)* sintheta)
-
-              c55 = sinphisq*(rhovsvsq*costhetasq + rhovshsq*sinthetasq) + &
-                  cosphisq*(rhovsvsq*costwothetasq + &
-                  (rhovphsq - two_eta_aniso*rhovphsq + rhovpvsq + four_eta_aniso*rhovsvsq)*costhetasq* sinthetasq)
-
-              c56 = costheta*sinphi*((cosphisq* &
-                  (rhovphsq - two_eta_aniso*rhovphsq + rhovpvsq - two_rhovshsq - two_rhovsvsq + &
-                  four_eta_aniso*rhovsvsq + (-rhovphsq + two_eta_aniso*rhovphsq - rhovpvsq + &
-                  four_rhovsvsq - four_eta_aniso*rhovsvsq)*costwotheta))/2. + &
-                  (-rhovshsq + rhovsvsq)*sinphisq)*sintheta
-
-              c66 = rhovshsq*costwophisq*costhetasq - &
-                  2.*(rhovphsq - two_rhovshsq)*cosphisq*costhetasq*sinphisq + &
-                  (rhovphsq*(11. + 4.*costwotheta + cosfourtheta)*sintwophisq)/32. - &
-                  (rhovsvsq*(-6. - 2.*cosfourphi + cos(4.*phi - 2.*theta) - 2.*costwotheta + &
-                  cos(2.*(2.*phi + theta)))*sinthetasq)/8. + &
-                  rhovpvsq*cosphisq*sinphisq*sinthetafour - &
-                  (eta_aniso*(rhovphsq - two_rhovsvsq)*sintwophisq*sinthetafour)/2.
-
-              ! general expression of stress tensor for full Cijkl with 21 coefficients
-              sigma_xx = c11*duxdxl + c16*duxdyl_plus_duydxl + c12*duydyl + &
-                       c15*duzdxl_plus_duxdzl + c14*duzdyl_plus_duydzl + c13*duzdzl
-
-              sigma_yy = c12*duxdxl + c26*duxdyl_plus_duydxl + c22*duydyl + &
-                       c25*duzdxl_plus_duxdzl + c24*duzdyl_plus_duydzl + c23*duzdzl
-
-              sigma_zz = c13*duxdxl + c36*duxdyl_plus_duydxl + c23*duydyl + &
-                       c35*duzdxl_plus_duxdzl + c34*duzdyl_plus_duydzl + c33*duzdzl
-
-              sigma_xy = c16*duxdxl + c66*duxdyl_plus_duydxl + c26*duydyl + &
-                       c56*duzdxl_plus_duxdzl + c46*duzdyl_plus_duydzl + c36*duzdzl
-
-              sigma_xz = c15*duxdxl + c56*duxdyl_plus_duydxl + c25*duydyl + &
-                       c55*duzdxl_plus_duxdzl + c45*duzdyl_plus_duydzl + c35*duzdzl
-
-              sigma_yz = c14*duxdxl + c46*duxdyl_plus_duydxl + c24*duydyl + &
-                       c45*duzdxl_plus_duxdzl + c44*duzdyl_plus_duydzl + c34*duzdzl
-
-            endif
-
-          endif   ! end of test whether isotropic or anisotropic element
-
-          ! subtract memory variables if attenuation
-          if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. )  ) then
-! way 1:
-!            do i_SLS = 1,N_SLS
-!              R_xx_val = R_memory(1,i_SLS,i,j,k,ispec)
-!              R_yy_val = R_memory(2,i_SLS,i,j,k,ispec)
-!              sigma_xx = sigma_xx - R_xx_val
-!              sigma_yy = sigma_yy - R_yy_val
-!              sigma_zz = sigma_zz + R_xx_val + R_yy_val
-!              sigma_xy = sigma_xy - R_memory(3,i_SLS,i,j,k,ispec)
-!              sigma_xz = sigma_xz - R_memory(4,i_SLS,i,j,k,ispec)
-!              sigma_yz = sigma_yz - R_memory(5,i_SLS,i,j,k,ispec)
-!            enddo
-
-! way 2:
-! note: this should help compilers to pipeline the code and make better use of the cache;
-!          depending on compilers, it can further decrease the computation time by ~ 30%.
-!          by default, N_SLS = 3, therefore we take steps of 3
-          if(imodulo_N_SLS >= 1) then
-            do i_SLS = 1,imodulo_N_SLS
-              R_xx_val1 = R_memory(1,i_SLS,i,j,k,ispec)
-              R_yy_val1 = R_memory(2,i_SLS,i,j,k,ispec)
-              sigma_xx = sigma_xx - R_xx_val1
-              sigma_yy = sigma_yy - R_yy_val1
-              sigma_zz = sigma_zz + R_xx_val1 + R_yy_val1
-              sigma_xy = sigma_xy - R_memory(3,i_SLS,i,j,k,ispec)
-              sigma_xz = sigma_xz - R_memory(4,i_SLS,i,j,k,ispec)
-              sigma_yz = sigma_yz - R_memory(5,i_SLS,i,j,k,ispec)
-            enddo
-          endif
-
-          if(N_SLS >= imodulo_N_SLS+1) then
-            do i_SLS = imodulo_N_SLS+1,N_SLS,3
-              R_xx_val1 = R_memory(1,i_SLS,i,j,k,ispec)
-              R_yy_val1 = R_memory(2,i_SLS,i,j,k,ispec)
-              sigma_xx = sigma_xx - R_xx_val1
-              sigma_yy = sigma_yy - R_yy_val1
-              sigma_zz = sigma_zz + R_xx_val1 + R_yy_val1
-              sigma_xy = sigma_xy - R_memory(3,i_SLS,i,j,k,ispec)
-              sigma_xz = sigma_xz - R_memory(4,i_SLS,i,j,k,ispec)
-              sigma_yz = sigma_yz - R_memory(5,i_SLS,i,j,k,ispec)
-
-              R_xx_val2 = R_memory(1,i_SLS+1,i,j,k,ispec)
-              R_yy_val2 = R_memory(2,i_SLS+1,i,j,k,ispec)
-              sigma_xx = sigma_xx - R_xx_val2
-              sigma_yy = sigma_yy - R_yy_val2
-              sigma_zz = sigma_zz + R_xx_val2 + R_yy_val2
-              sigma_xy = sigma_xy - R_memory(3,i_SLS+1,i,j,k,ispec)
-              sigma_xz = sigma_xz - R_memory(4,i_SLS+1,i,j,k,ispec)
-              sigma_yz = sigma_yz - R_memory(5,i_SLS+1,i,j,k,ispec)
-
-              R_xx_val3 = R_memory(1,i_SLS+2,i,j,k,ispec)
-              R_yy_val3 = R_memory(2,i_SLS+2,i,j,k,ispec)
-              sigma_xx = sigma_xx - R_xx_val3
-              sigma_yy = sigma_yy - R_yy_val3
-              sigma_zz = sigma_zz + R_xx_val3 + R_yy_val3
-              sigma_xy = sigma_xy - R_memory(3,i_SLS+2,i,j,k,ispec)
-              sigma_xz = sigma_xz - R_memory(4,i_SLS+2,i,j,k,ispec)
-              sigma_yz = sigma_yz - R_memory(5,i_SLS+2,i,j,k,ispec)
-            enddo
-          endif
-
-          endif
-
-          ! define symmetric components of sigma for gravity
-          sigma_yx = sigma_xy
-          sigma_zx = sigma_xz
-          sigma_zy = sigma_yz
-
-          ! compute non-symmetric terms for gravity
-          if(GRAVITY_VAL) then
-
-            ! use mesh coordinates to get theta and phi
-            ! x y and z contain r theta and phi
-            iglob1 = ibool(i,j,k,ispec)
-            theta = ystore(iglob1)
-            phi = zstore(iglob1)
-
-            cos_theta = dcos(dble(theta))
-            sin_theta = dsin(dble(theta))
-            cos_phi = dcos(dble(phi))
-            sin_phi = dsin(dble(phi))
-
-            cos_theta_sq = cos_theta**2
-            sin_theta_sq = sin_theta**2
-            cos_phi_sq = cos_phi**2
-            sin_phi_sq = sin_phi**2
-
-            ! get g, rho and dg/dr=dg
-            ! spherical components of the gravitational acceleration
-            ! for efficiency replace with lookup table every 100 m in radial direction
-            radius = dble(xstore(iglob1))
-            int_radius = nint(radius * R_EARTH_KM * 10.d0)
-            minus_g = minus_gravity_table(int_radius)
-            minus_dg = minus_deriv_gravity_table(int_radius)
-            rho = density_table(int_radius)
-
-            ! Cartesian components of the gravitational acceleration
-            gxl = minus_g*sin_theta*cos_phi
-            gyl = minus_g*sin_theta*sin_phi
-            gzl = minus_g*cos_theta
-
-            ! Cartesian components of gradient of gravitational acceleration
-            ! obtained from spherical components
-            minus_g_over_radius = minus_g / radius
-            minus_dg_plus_g_over_radius = minus_dg - minus_g_over_radius
-
-            Hxxl = minus_g_over_radius*(cos_phi_sq*cos_theta_sq + sin_phi_sq) + cos_phi_sq*minus_dg*sin_theta_sq
-            Hyyl = minus_g_over_radius*(cos_phi_sq + cos_theta_sq*sin_phi_sq) + minus_dg*sin_phi_sq*sin_theta_sq
-            Hzzl = cos_theta_sq*minus_dg + minus_g_over_radius*sin_theta_sq
-            Hxyl = cos_phi*minus_dg_plus_g_over_radius*sin_phi*sin_theta_sq
-            Hxzl = cos_phi*cos_theta*minus_dg_plus_g_over_radius*sin_theta
-            Hyzl = cos_theta*minus_dg_plus_g_over_radius*sin_phi*sin_theta
-
-
-            ! for locality principle, we set iglob again, in order to have it in the cache again
-            iglob1 = ibool(i,j,k,ispec)
-
-            ! distinguish between single and double precision for reals
-            if(CUSTOM_REAL == SIZE_REAL) then
-
-              ! get displacement and multiply by density to compute G tensor
-              sx_l = rho * dble(displ_crust_mantle(1,iglob1))
-              sy_l = rho * dble(displ_crust_mantle(2,iglob1))
-              sz_l = rho * dble(displ_crust_mantle(3,iglob1))
-
-              ! compute G tensor from s . g and add to sigma (not symmetric)
-              sigma_xx = sigma_xx + sngl(sy_l*gyl + sz_l*gzl)
-              sigma_yy = sigma_yy + sngl(sx_l*gxl + sz_l*gzl)
-              sigma_zz = sigma_zz + sngl(sx_l*gxl + sy_l*gyl)
-
-              sigma_xy = sigma_xy - sngl(sx_l * gyl)
-              sigma_yx = sigma_yx - sngl(sy_l * gxl)
-
-              sigma_xz = sigma_xz - sngl(sx_l * gzl)
-              sigma_zx = sigma_zx - sngl(sz_l * gxl)
-
-              sigma_yz = sigma_yz - sngl(sy_l * gzl)
-              sigma_zy = sigma_zy - sngl(sz_l * gyl)
-
-              ! precompute vector
-              factor = dble(jacobianl) * wgll_cube(i,j,k)
-              rho_s_H(1,i,j,k) = sngl(factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl))
-              rho_s_H(2,i,j,k) = sngl(factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl))
-              rho_s_H(3,i,j,k) = sngl(factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl))
-
-            else
-
-              ! get displacement and multiply by density to compute G tensor
-              sx_l = rho * displ_crust_mantle(1,iglob1)
-              sy_l = rho * displ_crust_mantle(2,iglob1)
-              sz_l = rho * displ_crust_mantle(3,iglob1)
-
-              ! compute G tensor from s . g and add to sigma (not symmetric)
-              sigma_xx = sigma_xx + sy_l*gyl + sz_l*gzl
-              sigma_yy = sigma_yy + sx_l*gxl + sz_l*gzl
-              sigma_zz = sigma_zz + sx_l*gxl + sy_l*gyl
-
-              sigma_xy = sigma_xy - sx_l * gyl
-              sigma_yx = sigma_yx - sy_l * gxl
-
-              sigma_xz = sigma_xz - sx_l * gzl
-              sigma_zx = sigma_zx - sz_l * gxl
-
-              sigma_yz = sigma_yz - sy_l * gzl
-              sigma_zy = sigma_zy - sz_l * gyl
-
-              ! precompute vector
-              factor = jacobianl * wgll_cube(i,j,k)
-              rho_s_H(1,i,j,k) = factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl)
-              rho_s_H(2,i,j,k) = factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl)
-              rho_s_H(3,i,j,k) = factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl)
-
-            endif
-
-          endif  ! end of section with gravity terms
-
-          ! form dot product with test vector, non-symmetric form
-          tempx1(i,j,k) = jacobianl * (sigma_xx*xixl + sigma_yx*xiyl + sigma_zx*xizl)
-          tempy1(i,j,k) = jacobianl * (sigma_xy*xixl + sigma_yy*xiyl + sigma_zy*xizl)
-          tempz1(i,j,k) = jacobianl * (sigma_xz*xixl + sigma_yz*xiyl + sigma_zz*xizl)
-
-          tempx2(i,j,k) = jacobianl * (sigma_xx*etaxl + sigma_yx*etayl + sigma_zx*etazl)
-          tempy2(i,j,k) = jacobianl * (sigma_xy*etaxl + sigma_yy*etayl + sigma_zy*etazl)
-          tempz2(i,j,k) = jacobianl * (sigma_xz*etaxl + sigma_yz*etayl + sigma_zz*etazl)
-
-          tempx3(i,j,k) = jacobianl * (sigma_xx*gammaxl + sigma_yx*gammayl + sigma_zx*gammazl)
-          tempy3(i,j,k) = jacobianl * (sigma_xy*gammaxl + sigma_yy*gammayl + sigma_zy*gammazl)
-          tempz3(i,j,k) = jacobianl * (sigma_xz*gammaxl + sigma_yz*gammayl + sigma_zz*gammazl)
-        enddo ! NGLLX
-      enddo ! NGLLY
-    enddo ! NGLLZ
-
-    ! subroutines adapted from Deville, Fischer and Mund, High-order methods
-    ! for incompressible fluid flow, Cambridge University Press (2002),
-    ! pages 386 and 389 and Figure 8.3.1
-    do j=1,m2
-      do i=1,m1
-        E1_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C1_m1_m2_5points(1,j) + &
-                              hprimewgll_xxT(i,2)*C1_m1_m2_5points(2,j) + &
-                              hprimewgll_xxT(i,3)*C1_m1_m2_5points(3,j) + &
-                              hprimewgll_xxT(i,4)*C1_m1_m2_5points(4,j) + &
-                              hprimewgll_xxT(i,5)*C1_m1_m2_5points(5,j)
-
-        E2_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C2_m1_m2_5points(1,j) + &
-                              hprimewgll_xxT(i,2)*C2_m1_m2_5points(2,j) + &
-                              hprimewgll_xxT(i,3)*C2_m1_m2_5points(3,j) + &
-                              hprimewgll_xxT(i,4)*C2_m1_m2_5points(4,j) + &
-                              hprimewgll_xxT(i,5)*C2_m1_m2_5points(5,j)
-
-        E3_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C3_m1_m2_5points(1,j) + &
-                              hprimewgll_xxT(i,2)*C3_m1_m2_5points(2,j) + &
-                              hprimewgll_xxT(i,3)*C3_m1_m2_5points(3,j) + &
-                              hprimewgll_xxT(i,4)*C3_m1_m2_5points(4,j) + &
-                              hprimewgll_xxT(i,5)*C3_m1_m2_5points(5,j)
-      enddo
-    enddo
-    do i=1,m1
-      do j=1,m1
-        ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
-        do k = 1,NGLLX
-          newtempx2(i,j,k) = tempx2(i,1,k)*hprimewgll_xx(1,j) + &
-                           tempx2(i,2,k)*hprimewgll_xx(2,j) + &
-                           tempx2(i,3,k)*hprimewgll_xx(3,j) + &
-                           tempx2(i,4,k)*hprimewgll_xx(4,j) + &
-                           tempx2(i,5,k)*hprimewgll_xx(5,j)
-
-          newtempy2(i,j,k) = tempy2(i,1,k)*hprimewgll_xx(1,j) + &
-                           tempy2(i,2,k)*hprimewgll_xx(2,j) + &
-                           tempy2(i,3,k)*hprimewgll_xx(3,j) + &
-                           tempy2(i,4,k)*hprimewgll_xx(4,j) + &
-                           tempy2(i,5,k)*hprimewgll_xx(5,j)
-
-          newtempz2(i,j,k) = tempz2(i,1,k)*hprimewgll_xx(1,j) + &
-                           tempz2(i,2,k)*hprimewgll_xx(2,j) + &
-                           tempz2(i,3,k)*hprimewgll_xx(3,j) + &
-                           tempz2(i,4,k)*hprimewgll_xx(4,j) + &
-                           tempz2(i,5,k)*hprimewgll_xx(5,j)
-        enddo
-      enddo
-    enddo
-    do j=1,m1
-      do i=1,m2
-        E1_mxm_m2_m1_5points(i,j) = C1_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
-                                  C1_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
-                                  C1_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
-                                  C1_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
-                                  C1_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
-
-        E2_mxm_m2_m1_5points(i,j) = C2_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
-                                  C2_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
-                                  C2_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
-                                  C2_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
-                                  C2_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
-
-        E3_mxm_m2_m1_5points(i,j) = C3_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
-                                  C3_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
-                                  C3_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
-                                  C3_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
-                                  C3_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
-      enddo
-    enddo
-
-    do k=1,NGLLZ
-      do j=1,NGLLY
-
-! way 1:
-! this seems to be still the fastest way here.
-        fac1 = wgllwgll_yz(j,k)
-        do i=1,NGLLX
-          fac2 = wgllwgll_xz(i,k)
-          fac3 = wgllwgll_xy(i,j)
-
-          ! sum contributions
-          sum_terms(1,i,j,k) = - (fac1*newtempx1(i,j,k) + fac2*newtempx2(i,j,k) + fac3*newtempx3(i,j,k))
-          sum_terms(2,i,j,k) = - (fac1*newtempy1(i,j,k) + fac2*newtempy2(i,j,k) + fac3*newtempy3(i,j,k))
-          sum_terms(3,i,j,k) = - (fac1*newtempz1(i,j,k) + fac2*newtempz2(i,j,k) + fac3*newtempz3(i,j,k))
-
-          if(GRAVITY_VAL) sum_terms(:,i,j,k) = sum_terms(:,i,j,k) + rho_s_H(:,i,j,k)
-
-        enddo ! NGLLX
-
-      enddo ! NGLLY
-    enddo ! NGLLZ
-
-    ! sum contributions from each element to the global mesh and add gravity terms
-    do k=1,NGLLZ
-      do j=1,NGLLY
-! way 1:
-!        do i=1,NGLLX
-!          iglob = ibool(i,j,k,ispec)
-!          accel_crust_mantle(:,iglob) = accel_crust_mantle(:,iglob) + sum_terms(:,i,j,k)
-!        enddo
-
-! way 2:
-        accel_crust_mantle(:,ibool(1,j,k,ispec)) = accel_crust_mantle(:,ibool(1,j,k,ispec)) + sum_terms(:,1,j,k)
-        accel_crust_mantle(:,ibool(2,j,k,ispec)) = accel_crust_mantle(:,ibool(2,j,k,ispec)) + sum_terms(:,2,j,k)
-        accel_crust_mantle(:,ibool(3,j,k,ispec)) = accel_crust_mantle(:,ibool(3,j,k,ispec)) + sum_terms(:,3,j,k)
-        accel_crust_mantle(:,ibool(4,j,k,ispec)) = accel_crust_mantle(:,ibool(4,j,k,ispec)) + sum_terms(:,4,j,k)
-        accel_crust_mantle(:,ibool(5,j,k,ispec)) = accel_crust_mantle(:,ibool(5,j,k,ispec)) + sum_terms(:,5,j,k)
-
-      enddo
-    enddo
-
-    ! update memory variables based upon the Runge-Kutta scheme
-    ! convention for attenuation
-    ! term in xx = 1
-    ! term in yy = 2
-    ! term in xy = 3
-    ! term in xz = 4
-    ! term in yz = 5
-    ! term in zz not computed since zero trace
-    ! This is because we only implement Q_\mu attenuation and not Q_\kappa.
-    ! Note that this does *NOT* imply that there is no attenuation for P waves
-    ! because for Q_\kappa = infinity one gets (see for instance Dahlen and Tromp (1998)
-    ! equation (9.59) page 350): Q_\alpha = Q_\mu * 3 * (V_p/V_s)^2 / 4
-    ! therefore Q_\alpha is not zero; for instance for V_p / V_s = sqrt(3)
-    ! we get Q_\alpha = (9 / 4) * Q_\mu = 2.25 * Q_\mu
-
-    if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. ) ) then
-
-      ! use Runge-Kutta scheme to march in time
-
-      ! get coefficients for that standard linear solid
-      ! IMPROVE we use mu_v here even if there is some anisotropy
-      ! IMPROVE we should probably use an average value instead
-
-! way 1:
-! it still seems to be the fastest way here.
-      do i_SLS = 1,N_SLS
-        ! reformatted R_memory to handle large factor_common and reduced [alpha,beta,gamma]val
-        factor_common_c44_muv = factor_common(i_SLS,:,:,:,ispec)
-
-        if(ANISOTROPIC_3D_MANTLE_VAL) then
-          factor_common_c44_muv = factor_common_c44_muv * c44store(:,:,:,ispec)
-        else
-          factor_common_c44_muv = factor_common_c44_muv * muvstore(:,:,:,ispec)
-        endif
-
-        do i_memory = 1,5
-          R_memory(i_memory,i_SLS,:,:,:,ispec) = alphaval(i_SLS) * &
-                    R_memory(i_memory,i_SLS,:,:,:,ispec) + &
-                    factor_common_c44_muv * &
-                    (betaval(i_SLS) * epsilondev(i_memory,:,:,:,ispec) + &
-                    gammaval(i_SLS) * epsilondev_loc(i_memory,:,:,:))
-        enddo
-      enddo
-
-    endif
-
-    ! save deviatoric strain for Runge-Kutta scheme
-    if(COMPUTE_AND_STORE_STRAIN) then
-! way 1:
-      !epsilondev(:,:,:,:,ispec) = epsilondev_loc(:,:,:,:)
-! way 2:
-      do k=1,NGLLZ
-        do j=1,NGLLY
-            !dummy(:) = epsilondev_loc(:,1,j,k)
-
-            epsilondev(:,1,j,k,ispec) = epsilondev_loc(:,1,j,k)
-            epsilondev(:,2,j,k,ispec) = epsilondev_loc(:,2,j,k)
-            epsilondev(:,3,j,k,ispec) = epsilondev_loc(:,3,j,k)
-            epsilondev(:,4,j,k,ispec) = epsilondev_loc(:,4,j,k)
-            epsilondev(:,5,j,k,ispec) = epsilondev_loc(:,5,j,k)
-        enddo
-      enddo
-    endif
-
-  enddo   ! spectral element loop NSPEC_CRUST_MANTLE
-
-  end subroutine compute_forces_crust_mantle_Dev
-

Copied: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.F90 (from rev 18970, seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.f90)
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.F90	                        (rev 0)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.F90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -0,0 +1,823 @@
+!=====================================================================
+!
+!          S p e c f e m 3 D  G l o b e  V e r s i o n  5 . 1
+!          --------------------------------------------------
+!
+!          Main authors: Dimitri Komatitsch and Jeroen Tromp
+!                        Princeton University, USA
+!             and University of Pau / CNRS / INRIA, France
+! (c) Princeton University / California Institute of Technology and University of Pau / CNRS / INRIA
+!                            April 2011
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or
+! (at your option) any later version.
+!
+! This program is distributed in the hope that it will be useful,
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+! GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along
+! with this program; if not, write to the Free Software Foundation, Inc.,
+! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+!
+!=====================================================================
+
+! preprocessing definition: #define _HANDOPT :  turns hand-optimized code on
+!                                         #undef _HANDOPT :  turns hand-optimized code off
+! or compile with: -D_HANDOPT
+!#define _HANDOPT
+ 
+! note: these hand optimizations should help compilers to pipeline the code and make better use of the cache;
+!          depending on compilers, it can further decrease the computation time by ~ 30%.
+!          the original routines are commented with "! way 1", the hand-optimized routines with  "! way 2"
+
+  subroutine compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_inner_core,accel_inner_core,xstore,ystore,zstore, &
+          xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
+!----------------------
+            is_on_a_slice_edge_inner_core,icall, &
+            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_INNER_CORE,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore,muvstore,ibool,idoubling, &
+          c11store,c33store,c12store,c13store,c44store,R_memory,epsilondev,epsilon_trace_over_3,&
+          one_minus_sum_beta,alphaval,betaval,gammaval,factor_common, &
+          vx,vy,vz,vnspec)
+
+! this routine is optimized for NGLLX = NGLLY = NGLLZ = 5 using the Deville et al. (2002) inlined matrix-matrix products
+
+  implicit none
+
+  include "constants.h"
+
+! include values created by the mesher
+! done for performance only using static allocation to allow for loop unrolling
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  ! displacement and acceleration
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: displ_inner_core,accel_inner_core
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool
+
+  real(kind=CUSTOM_REAL), dimension(NGLOB_INNER_CORE) :: xstore,ystore,zstore
+
+  ! arrays with mesh parameters per slice
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: xix,xiy,xiz, &
+                      etax,etay,etaz,gammax,gammay,gammaz
+
+  ! for attenuation
+  ! memory variables R_ij are stored at the local rather than global level
+  ! to allow for optimization of cache access by compiler
+  ! variable lengths for factor_common and one_minus_sum_beta
+  integer vx, vy, vz, vnspec
+  real(kind=CUSTOM_REAL), dimension(N_SLS, vx, vy, vz, vnspec) :: factor_common
+  real(kind=CUSTOM_REAL), dimension(vx, vy, vz, vnspec) :: one_minus_sum_beta
+
+  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval,betaval,gammaval
+
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ATTENUATION) :: R_memory
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: epsilondev
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: epsilon_trace_over_3
+
+  ! array with derivatives of Lagrange polynomials and precalculated products
+  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xx,hprimewgll_xx
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xxT,hprimewgll_xxT
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY) :: wgllwgll_xy
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ) :: wgllwgll_xz
+  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ) :: wgllwgll_yz
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: kappavstore,muvstore
+
+!  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: &
+!    c11store,c33store,c12store,c13store,c44store
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_IC) :: &
+    c11store,c33store,c12store,c13store,c44store
+
+  ! array with the local to global mapping per slice
+  integer, dimension(NSPEC_INNER_CORE) :: idoubling
+
+  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table,density_table,minus_deriv_gravity_table
+
+! local parameters
+  ! Deville
+  ! manually inline the calls to the Deville et al. (2002) routines
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: &
+    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: dummyx_loc,dummyy_loc,dummyz_loc, &
+    newtempx1,newtempx2,newtempx3,newtempy1,newtempy2,newtempy3,newtempz1,newtempz2,newtempz3
+  real(kind=CUSTOM_REAL), dimension(NGLLX,m2) :: B1_m1_m2_5points,B2_m1_m2_5points,B3_m1_m2_5points
+  real(kind=CUSTOM_REAL), dimension(m1,m2) :: C1_m1_m2_5points,C2_m1_m2_5points,C3_m1_m2_5points
+  real(kind=CUSTOM_REAL), dimension(m1,m2) :: E1_m1_m2_5points,E2_m1_m2_5points,E3_m1_m2_5points
+
+  equivalence(dummyx_loc,B1_m1_m2_5points)
+  equivalence(dummyy_loc,B2_m1_m2_5points)
+  equivalence(dummyz_loc,B3_m1_m2_5points)
+  equivalence(tempx1,C1_m1_m2_5points)
+  equivalence(tempy1,C2_m1_m2_5points)
+  equivalence(tempz1,C3_m1_m2_5points)
+  equivalence(newtempx1,E1_m1_m2_5points)
+  equivalence(newtempy1,E2_m1_m2_5points)
+  equivalence(newtempz1,E3_m1_m2_5points)
+
+  real(kind=CUSTOM_REAL), dimension(m2,NGLLX) :: &
+    A1_mxm_m2_m1_5points,A2_mxm_m2_m1_5points,A3_mxm_m2_m1_5points
+  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
+    C1_mxm_m2_m1_5points,C2_mxm_m2_m1_5points,C3_mxm_m2_m1_5points
+  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
+    E1_mxm_m2_m1_5points,E2_mxm_m2_m1_5points,E3_mxm_m2_m1_5points
+
+  equivalence(dummyx_loc,A1_mxm_m2_m1_5points)
+  equivalence(dummyy_loc,A2_mxm_m2_m1_5points)
+  equivalence(dummyz_loc,A3_mxm_m2_m1_5points)
+  equivalence(tempx3,C1_mxm_m2_m1_5points)
+  equivalence(tempy3,C2_mxm_m2_m1_5points)
+  equivalence(tempz3,C3_mxm_m2_m1_5points)
+  equivalence(newtempx3,E1_mxm_m2_m1_5points)
+  equivalence(newtempy3,E2_mxm_m2_m1_5points)
+  equivalence(newtempz3,E3_mxm_m2_m1_5points)
+
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: sum_terms
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
+
+  real(kind=CUSTOM_REAL) xixl,xiyl,xizl,etaxl,etayl,etazl,gammaxl,gammayl,gammazl,jacobianl
+  real(kind=CUSTOM_REAL) duxdxl,duxdyl,duxdzl,duydxl,duydyl,duydzl,duzdxl,duzdyl,duzdzl
+
+  real(kind=CUSTOM_REAL) duxdxl_plus_duydyl,duxdxl_plus_duzdzl,duydyl_plus_duzdzl
+  real(kind=CUSTOM_REAL) duxdyl_plus_duydxl,duzdxl_plus_duxdzl,duzdyl_plus_duydzl
+
+  real(kind=CUSTOM_REAL) sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz
+
+  real(kind=CUSTOM_REAL) fac1,fac2,fac3,templ
+  real(kind=CUSTOM_REAL) lambdal,mul,lambdalplus2mul
+  real(kind=CUSTOM_REAL) kappal
+
+  real(kind=CUSTOM_REAL) minus_sum_beta
+  real(kind=CUSTOM_REAL) c11l,c33l,c12l,c13l,c44l
+
+  ! for gravity
+  double precision radius,rho,minus_g,minus_dg
+  double precision minus_g_over_radius,minus_dg_plus_g_over_radius
+  double precision cos_theta,sin_theta,cos_phi,sin_phi
+  double precision cos_theta_sq,sin_theta_sq,cos_phi_sq,sin_phi_sq
+  double precision theta,phi,factor,gxl,gyl,gzl,sx_l,sy_l,sz_l
+  double precision Hxxl,Hyyl,Hzzl,Hxyl,Hxzl,Hyzl
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: rho_s_H
+  real(kind=CUSTOM_REAL) sigma_yx,sigma_zx,sigma_zy
+
+  integer :: int_radius
+  integer :: ispec,ispec_strain
+  integer :: i,j,k
+  integer :: iglob1
+
+! this for non blocking MPI
+  integer :: iphase,icall
+
+  integer :: computed_elements
+
+  logical, dimension(NSPEC_INNER_CORE) :: is_on_a_slice_edge_inner_core
+
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: accel_crust_mantle
+
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool_inner_core
+
+  integer, dimension(NSPEC_INNER_CORE) :: idoubling_inner_core
+
+  integer :: ichunk,iproc_xi,iproc_eta,myrank
+
+  integer, dimension(NCHUNKS_VAL,0:NPROC_XI_VAL-1,0:NPROC_ETA_VAL-1) :: addressing
+
+  integer, dimension(NGLOB2DMAX_XMIN_XMAX_CM) :: iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle
+  integer, dimension(NGLOB2DMAX_YMIN_YMAX_CM) :: iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle
+
+  integer, dimension(NGLOB2DMAX_XMIN_XMAX_IC) :: iboolleft_xi_inner_core,iboolright_xi_inner_core
+  integer, dimension(NGLOB2DMAX_YMIN_YMAX_IC) :: iboolleft_eta_inner_core,iboolright_eta_inner_core
+
+  integer npoin2D_faces_crust_mantle(NUMFACES_SHARED)
+  integer npoin2D_faces_inner_core(NUMFACES_SHARED)
+
+  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+       npoin2D_xi_inner_core,npoin2D_eta_inner_core
+
+! communication pattern for faces between chunks
+  integer, dimension(NUMMSGS_FACES_VAL) :: iprocfrom_faces,iprocto_faces
+
+! communication pattern for corners between chunks
+  integer, dimension(NCORNERSCHUNKS_VAL) :: iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners
+
+  integer, dimension(NGLOB1D_RADIAL_CM,NUMCORNERS_SHARED) :: iboolcorner_crust_mantle
+  integer, dimension(NGLOB1D_RADIAL_IC,NUMCORNERS_SHARED) :: iboolcorner_inner_core
+
+  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_crust_mantle
+  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_inner_core
+
+  integer :: npoin2D_max_all_CM_IC
+  real(kind=CUSTOM_REAL), dimension(NDIM,npoin2D_max_all_CM_IC) :: buffer_send_faces,buffer_received_faces
+
+! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB1D_RADIAL_CM + NGLOB1D_RADIAL_IC) :: &
+     buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector
+
+! for matching with central cube in inner core
+  integer nb_msgs_theor_in_cube, npoin2D_cube_from_slices,iphase_CC
+  integer, dimension(nb_msgs_theor_in_cube) :: sender_from_slices_to_cube
+  double precision, dimension(npoin2D_cube_from_slices,NDIM) :: buffer_slices
+  double precision, dimension(npoin2D_cube_from_slices,NDIM,nb_msgs_theor_in_cube) :: buffer_all_cube_from_slices
+  integer, dimension(nb_msgs_theor_in_cube,npoin2D_cube_from_slices):: ibool_central_cube
+  integer receiver_cube_from_slices
+  logical :: INCLUDE_CENTRAL_CUBE
+
+! local to global mapping
+  integer NSPEC2D_BOTTOM_INNER_CORE
+  integer, dimension(NSPEC2D_BOTTOM_INNER_CORE) :: ibelm_bottom_inner_core
+
+#ifdef _HANDOPT
+  integer, dimension(5) :: iglobv5
+#endif
+
+! ****************************************************
+!   big loop over all spectral elements in the solid
+! ****************************************************
+
+  computed_elements = 0
+
+  do ispec = 1,NSPEC_INNER_CORE
+
+! hide communications by computing the edges first
+    if((icall == 2 .and. is_on_a_slice_edge_inner_core(ispec)) .or. &
+       (icall == 1 .and. .not. is_on_a_slice_edge_inner_core(ispec))) cycle
+
+    ! exclude fictitious elements in central cube
+    if(idoubling(ispec) /= IFLAG_IN_FICTITIOUS_CUBE) then
+
+! process the communications every ELEMENTS_NONBLOCKING elements
+      computed_elements = computed_elements + 1
+      if (USE_NONBLOCKING_COMMS .and. icall == 2 .and. mod(computed_elements,ELEMENTS_NONBLOCKING_CM_IC) == 0) then
+
+        if(iphase <= 7) call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES_VAL,NCORNERSCHUNKS_VAL, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL_CM, &
+            NGLOB1D_RADIAL_IC,NCHUNKS_VAL,iphase)
+
+        if(INCLUDE_CENTRAL_CUBE) then
+          if(iphase > 7 .and. iphase_CC <= 4) &
+            call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+                   npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+                   receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
+                   ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,accel_inner_core,NDIM,iphase_CC)
+        endif
+
+      endif
+
+      ! subroutines adapted from Deville, Fischer and Mund, High-order methods
+      ! for incompressible fluid flow, Cambridge University Press (2002),
+      ! pages 386 and 389 and Figure 8.3.1
+      
+      do k=1,NGLLZ
+        do j=1,NGLLY
+#ifdef _HANDOPT        
+! way 2:
+        ! since we know that NGLLX = 5, this should help pipelining          
+        iglobv5(:) = ibool(:,j,k,ispec)
+        
+        dummyx_loc(1,j,k) = displ_inner_core(1,iglobv5(1))
+        dummyy_loc(1,j,k) = displ_inner_core(2,iglobv5(1))
+        dummyz_loc(1,j,k) = displ_inner_core(3,iglobv5(1))
+
+        dummyx_loc(2,j,k) = displ_inner_core(1,iglobv5(2))
+        dummyy_loc(2,j,k) = displ_inner_core(2,iglobv5(2))
+        dummyz_loc(2,j,k) = displ_inner_core(3,iglobv5(2))
+
+        dummyx_loc(3,j,k) = displ_inner_core(1,iglobv5(3))
+        dummyy_loc(3,j,k) = displ_inner_core(2,iglobv5(3))
+        dummyz_loc(3,j,k) = displ_inner_core(3,iglobv5(3))
+
+        dummyx_loc(4,j,k) = displ_inner_core(1,iglobv5(4))
+        dummyy_loc(4,j,k) = displ_inner_core(2,iglobv5(4))
+        dummyz_loc(4,j,k) = displ_inner_core(3,iglobv5(4))
+
+        dummyx_loc(5,j,k) = displ_inner_core(1,iglobv5(5))
+        dummyy_loc(5,j,k) = displ_inner_core(2,iglobv5(5))
+        dummyz_loc(5,j,k) = displ_inner_core(3,iglobv5(5))
+          
+#else
+! way 1:
+          do i=1,NGLLX
+            iglob1 = ibool(i,j,k,ispec)
+            dummyx_loc(i,j,k) = displ_inner_core(1,iglob1)
+            dummyy_loc(i,j,k) = displ_inner_core(2,iglob1)
+            dummyz_loc(i,j,k) = displ_inner_core(3,iglob1)
+          enddo
+#endif
+        enddo
+      enddo
+      
+      do j=1,m2
+        do i=1,m1
+          C1_m1_m2_5points(i,j) = hprime_xx(i,1)*B1_m1_m2_5points(1,j) + &
+                                hprime_xx(i,2)*B1_m1_m2_5points(2,j) + &
+                                hprime_xx(i,3)*B1_m1_m2_5points(3,j) + &
+                                hprime_xx(i,4)*B1_m1_m2_5points(4,j) + &
+                                hprime_xx(i,5)*B1_m1_m2_5points(5,j)
+
+          C2_m1_m2_5points(i,j) = hprime_xx(i,1)*B2_m1_m2_5points(1,j) + &
+                                hprime_xx(i,2)*B2_m1_m2_5points(2,j) + &
+                                hprime_xx(i,3)*B2_m1_m2_5points(3,j) + &
+                                hprime_xx(i,4)*B2_m1_m2_5points(4,j) + &
+                                hprime_xx(i,5)*B2_m1_m2_5points(5,j)
+
+          C3_m1_m2_5points(i,j) = hprime_xx(i,1)*B3_m1_m2_5points(1,j) + &
+                                hprime_xx(i,2)*B3_m1_m2_5points(2,j) + &
+                                hprime_xx(i,3)*B3_m1_m2_5points(3,j) + &
+                                hprime_xx(i,4)*B3_m1_m2_5points(4,j) + &
+                                hprime_xx(i,5)*B3_m1_m2_5points(5,j)
+        enddo
+      enddo
+      do j=1,m1
+        do i=1,m1
+          ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
+          do k = 1,NGLLX
+            tempx2(i,j,k) = dummyx_loc(i,1,k)*hprime_xxT(1,j) + &
+                          dummyx_loc(i,2,k)*hprime_xxT(2,j) + &
+                          dummyx_loc(i,3,k)*hprime_xxT(3,j) + &
+                          dummyx_loc(i,4,k)*hprime_xxT(4,j) + &
+                          dummyx_loc(i,5,k)*hprime_xxT(5,j)
+
+            tempy2(i,j,k) = dummyy_loc(i,1,k)*hprime_xxT(1,j) + &
+                          dummyy_loc(i,2,k)*hprime_xxT(2,j) + &
+                          dummyy_loc(i,3,k)*hprime_xxT(3,j) + &
+                          dummyy_loc(i,4,k)*hprime_xxT(4,j) + &
+                          dummyy_loc(i,5,k)*hprime_xxT(5,j)
+
+            tempz2(i,j,k) = dummyz_loc(i,1,k)*hprime_xxT(1,j) + &
+                          dummyz_loc(i,2,k)*hprime_xxT(2,j) + &
+                          dummyz_loc(i,3,k)*hprime_xxT(3,j) + &
+                          dummyz_loc(i,4,k)*hprime_xxT(4,j) + &
+                          dummyz_loc(i,5,k)*hprime_xxT(5,j)
+          enddo
+        enddo
+      enddo
+      do j=1,m1
+        do i=1,m2
+          C1_mxm_m2_m1_5points(i,j) = A1_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
+                                    A1_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
+                                    A1_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
+                                    A1_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
+                                    A1_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
+
+          C2_mxm_m2_m1_5points(i,j) = A2_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
+                                    A2_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
+                                    A2_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
+                                    A2_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
+                                    A2_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
+
+          C3_mxm_m2_m1_5points(i,j) = A3_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
+                                    A3_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
+                                    A3_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
+                                    A3_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
+                                    A3_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
+        enddo
+      enddo
+
+      do k=1,NGLLZ
+        do j=1,NGLLY
+          do i=1,NGLLX
+
+            ! get derivatives of ux, uy and uz with respect to x, y and z
+            xixl = xix(i,j,k,ispec)
+            xiyl = xiy(i,j,k,ispec)
+            xizl = xiz(i,j,k,ispec)
+            etaxl = etax(i,j,k,ispec)
+            etayl = etay(i,j,k,ispec)
+            etazl = etaz(i,j,k,ispec)
+            gammaxl = gammax(i,j,k,ispec)
+            gammayl = gammay(i,j,k,ispec)
+            gammazl = gammaz(i,j,k,ispec)
+
+            ! compute the jacobian
+            jacobianl = 1._CUSTOM_REAL / (xixl*(etayl*gammazl-etazl*gammayl) &
+                          - xiyl*(etaxl*gammazl-etazl*gammaxl) &
+                          + xizl*(etaxl*gammayl-etayl*gammaxl))
+
+            duxdxl = xixl*tempx1(i,j,k) + etaxl*tempx2(i,j,k) + gammaxl*tempx3(i,j,k)
+            duxdyl = xiyl*tempx1(i,j,k) + etayl*tempx2(i,j,k) + gammayl*tempx3(i,j,k)
+            duxdzl = xizl*tempx1(i,j,k) + etazl*tempx2(i,j,k) + gammazl*tempx3(i,j,k)
+
+            duydxl = xixl*tempy1(i,j,k) + etaxl*tempy2(i,j,k) + gammaxl*tempy3(i,j,k)
+            duydyl = xiyl*tempy1(i,j,k) + etayl*tempy2(i,j,k) + gammayl*tempy3(i,j,k)
+            duydzl = xizl*tempy1(i,j,k) + etazl*tempy2(i,j,k) + gammazl*tempy3(i,j,k)
+
+            duzdxl = xixl*tempz1(i,j,k) + etaxl*tempz2(i,j,k) + gammaxl*tempz3(i,j,k)
+            duzdyl = xiyl*tempz1(i,j,k) + etayl*tempz2(i,j,k) + gammayl*tempz3(i,j,k)
+            duzdzl = xizl*tempz1(i,j,k) + etazl*tempz2(i,j,k) + gammazl*tempz3(i,j,k)
+
+            ! precompute some sums to save CPU time
+            duxdxl_plus_duydyl = duxdxl + duydyl
+            duxdxl_plus_duzdzl = duxdxl + duzdzl
+            duydyl_plus_duzdzl = duydyl + duzdzl
+            duxdyl_plus_duydxl = duxdyl + duydxl
+            duzdxl_plus_duxdzl = duzdxl + duxdzl
+            duzdyl_plus_duydzl = duzdyl + duydzl
+
+            ! compute deviatoric strain
+            if (COMPUTE_AND_STORE_STRAIN) then
+              if(NSPEC_INNER_CORE_STRAIN_ONLY == 1) then
+                ispec_strain = 1
+              else
+                ispec_strain = ispec
+              endif
+              templ = ONE_THIRD * (duxdxl + duydyl + duzdzl)
+              epsilon_trace_over_3(i,j,k,ispec_strain) = templ
+              epsilondev_loc(1,i,j,k) = duxdxl - templ
+              epsilondev_loc(2,i,j,k) = duydyl - templ
+              epsilondev_loc(3,i,j,k) = 0.5 * duxdyl_plus_duydxl
+              epsilondev_loc(4,i,j,k) = 0.5 * duzdxl_plus_duxdzl
+              epsilondev_loc(5,i,j,k) = 0.5 * duzdyl_plus_duydzl
+            endif
+
+            if(ATTENUATION_VAL) then
+              minus_sum_beta =  one_minus_sum_beta(i,j,k,ispec) - 1.0
+            endif
+
+            if(ANISOTROPIC_INNER_CORE_VAL) then
+              ! elastic tensor for hexagonal symmetry in reduced notation:
+              !
+              !      c11 c12 c13  0   0        0
+              !      c12 c11 c13  0   0        0
+              !      c13 c13 c33  0   0        0
+              !       0   0   0  c44  0        0
+              !       0   0   0   0  c44       0
+              !       0   0   0   0   0  (c11-c12)/2
+              !
+              !       in terms of the A, C, L, N and F of Love (1927):
+              !
+              !       c11 = A
+              !       c12 = A-2N
+              !       c13 = F
+              !       c33 = C
+              !       c44 = L
+              c11l = c11store(i,j,k,ispec)
+              c12l = c12store(i,j,k,ispec)
+              c13l = c13store(i,j,k,ispec)
+              c33l = c33store(i,j,k,ispec)
+              c44l = c44store(i,j,k,ispec)
+
+              ! use unrelaxed parameters if attenuation
+              if(ATTENUATION_VAL) then
+                mul = muvstore(i,j,k,ispec)
+                c11l = c11l + FOUR_THIRDS * minus_sum_beta * mul
+                c12l = c12l - TWO_THIRDS * minus_sum_beta * mul
+                c13l = c13l - TWO_THIRDS * minus_sum_beta * mul
+                c33l = c33l + FOUR_THIRDS * minus_sum_beta * mul
+                c44l = c44l + minus_sum_beta * mul
+              endif
+
+              sigma_xx = c11l*duxdxl + c12l*duydyl + c13l*duzdzl
+              sigma_yy = c12l*duxdxl + c11l*duydyl + c13l*duzdzl
+              sigma_zz = c13l*duxdxl + c13l*duydyl + c33l*duzdzl
+              sigma_xy = 0.5*(c11l-c12l)*duxdyl_plus_duydxl
+              sigma_xz = c44l*duzdxl_plus_duxdzl
+              sigma_yz = c44l*duzdyl_plus_duydzl
+            else
+
+              ! inner core with no anisotropy, use kappav and muv for instance
+              ! layer with no anisotropy, use kappav and muv for instance
+              kappal = kappavstore(i,j,k,ispec)
+              mul = muvstore(i,j,k,ispec)
+
+              ! use unrelaxed parameters if attenuation
+              if(ATTENUATION_VAL) then
+                mul = mul * one_minus_sum_beta(i,j,k,ispec)
+              endif
+
+              lambdalplus2mul = kappal + FOUR_THIRDS * mul
+              lambdal = lambdalplus2mul - 2.*mul
+
+              ! compute stress sigma
+              sigma_xx = lambdalplus2mul*duxdxl + lambdal*duydyl_plus_duzdzl
+              sigma_yy = lambdalplus2mul*duydyl + lambdal*duxdxl_plus_duzdzl
+              sigma_zz = lambdalplus2mul*duzdzl + lambdal*duxdxl_plus_duydyl
+
+              sigma_xy = mul*duxdyl_plus_duydxl
+              sigma_xz = mul*duzdxl_plus_duxdzl
+              sigma_yz = mul*duzdyl_plus_duydzl
+
+            endif
+
+            ! subtract memory variables if attenuation
+            if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. ) ) then
+
+              ! note: fortran passes pointers to array location, thus R_memory(1,1,...) should be fine
+              call compute_element_att_stress( R_memory(1,1,i,j,k,ispec), &
+                    sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz)
+
+            endif
+
+            ! define symmetric components of sigma for gravity
+            sigma_yx = sigma_xy
+            sigma_zx = sigma_xz
+            sigma_zy = sigma_yz
+
+            ! compute non-symmetric terms for gravity
+            if(GRAVITY_VAL) then
+
+              ! use mesh coordinates to get theta and phi
+              ! x y and z contain r theta and phi
+              iglob1 = ibool(i,j,k,ispec)
+              radius = dble(xstore(iglob1))
+              theta = dble(ystore(iglob1))
+              phi = dble(zstore(iglob1))
+
+              ! make sure radius is never zero even for points at center of cube
+              ! because we later divide by radius
+              if(radius < 100.d0 / R_EARTH) radius = 100.d0 / R_EARTH
+
+              cos_theta = dcos(theta)
+              sin_theta = dsin(theta)
+              cos_phi = dcos(phi)
+              sin_phi = dsin(phi)
+
+              cos_theta_sq = cos_theta**2
+              sin_theta_sq = sin_theta**2
+              cos_phi_sq = cos_phi**2
+              sin_phi_sq = sin_phi**2
+
+              ! get g, rho and dg/dr=dg
+              ! spherical components of the gravitational acceleration
+              ! for efficiency replace with lookup table every 100 m in radial direction
+              ! make sure we never use zero for point exactly at the center of the Earth
+              int_radius = max(1,nint(radius * R_EARTH_KM * 10.d0))
+              minus_g = minus_gravity_table(int_radius)
+              minus_dg = minus_deriv_gravity_table(int_radius)
+              rho = density_table(int_radius)
+
+              ! Cartesian components of the gravitational acceleration
+              gxl = minus_g*sin_theta*cos_phi
+              gyl = minus_g*sin_theta*sin_phi
+              gzl = minus_g*cos_theta
+
+              ! Cartesian components of gradient of gravitational acceleration
+              ! obtained from spherical components
+              minus_g_over_radius = minus_g / radius
+              minus_dg_plus_g_over_radius = minus_dg - minus_g_over_radius
+
+              Hxxl = minus_g_over_radius*(cos_phi_sq*cos_theta_sq + sin_phi_sq) + cos_phi_sq*minus_dg*sin_theta_sq
+              Hyyl = minus_g_over_radius*(cos_phi_sq + cos_theta_sq*sin_phi_sq) + minus_dg*sin_phi_sq*sin_theta_sq
+              Hzzl = cos_theta_sq*minus_dg + minus_g_over_radius*sin_theta_sq
+              Hxyl = cos_phi*minus_dg_plus_g_over_radius*sin_phi*sin_theta_sq
+              Hxzl = cos_phi*cos_theta*minus_dg_plus_g_over_radius*sin_theta
+              Hyzl = cos_theta*minus_dg_plus_g_over_radius*sin_phi*sin_theta
+
+              ! for locality principle, we set iglob again, in order to have it in the cache again
+              iglob1 = ibool(i,j,k,ispec)
+
+              ! distinguish between single and double precision for reals
+              if(CUSTOM_REAL == SIZE_REAL) then
+                ! get displacement and multiply by density to compute G tensor
+                sx_l = rho * dble(displ_inner_core(1,iglob1))
+                sy_l = rho * dble(displ_inner_core(2,iglob1))
+                sz_l = rho * dble(displ_inner_core(3,iglob1))
+
+                ! compute G tensor from s . g and add to sigma (not symmetric)
+                sigma_xx = sigma_xx + sngl(sy_l*gyl + sz_l*gzl)
+                sigma_yy = sigma_yy + sngl(sx_l*gxl + sz_l*gzl)
+                sigma_zz = sigma_zz + sngl(sx_l*gxl + sy_l*gyl)
+
+                sigma_xy = sigma_xy - sngl(sx_l * gyl)
+                sigma_yx = sigma_yx - sngl(sy_l * gxl)
+
+                sigma_xz = sigma_xz - sngl(sx_l * gzl)
+                sigma_zx = sigma_zx - sngl(sz_l * gxl)
+
+                sigma_yz = sigma_yz - sngl(sy_l * gzl)
+                sigma_zy = sigma_zy - sngl(sz_l * gyl)
+
+                ! precompute vector
+                factor = dble(jacobianl) * wgll_cube(i,j,k)
+                rho_s_H(1,i,j,k) = sngl(factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl))
+                rho_s_H(2,i,j,k) = sngl(factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl))
+                rho_s_H(3,i,j,k) = sngl(factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl))
+
+              else
+
+                ! get displacement and multiply by density to compute G tensor
+                sx_l = rho * displ_inner_core(1,iglob1)
+                sy_l = rho * displ_inner_core(2,iglob1)
+                sz_l = rho * displ_inner_core(3,iglob1)
+
+                ! compute G tensor from s . g and add to sigma (not symmetric)
+                sigma_xx = sigma_xx + sy_l*gyl + sz_l*gzl
+                sigma_yy = sigma_yy + sx_l*gxl + sz_l*gzl
+                sigma_zz = sigma_zz + sx_l*gxl + sy_l*gyl
+
+                sigma_xy = sigma_xy - sx_l * gyl
+                sigma_yx = sigma_yx - sy_l * gxl
+
+                sigma_xz = sigma_xz - sx_l * gzl
+                sigma_zx = sigma_zx - sz_l * gxl
+
+                sigma_yz = sigma_yz - sy_l * gzl
+                sigma_zy = sigma_zy - sz_l * gyl
+
+                ! precompute vector
+                factor = jacobianl * wgll_cube(i,j,k)
+                rho_s_H(1,i,j,k) = factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl)
+                rho_s_H(2,i,j,k) = factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl)
+                rho_s_H(3,i,j,k) = factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl)
+
+              endif
+
+            endif  ! end of section with gravity terms
+
+            ! form dot product with test vector, non-symmetric form
+            tempx1(i,j,k) = jacobianl * (sigma_xx*xixl + sigma_yx*xiyl + sigma_zx*xizl)
+            tempy1(i,j,k) = jacobianl * (sigma_xy*xixl + sigma_yy*xiyl + sigma_zy*xizl)
+            tempz1(i,j,k) = jacobianl * (sigma_xz*xixl + sigma_yz*xiyl + sigma_zz*xizl)
+
+            tempx2(i,j,k) = jacobianl * (sigma_xx*etaxl + sigma_yx*etayl + sigma_zx*etazl)
+            tempy2(i,j,k) = jacobianl * (sigma_xy*etaxl + sigma_yy*etayl + sigma_zy*etazl)
+            tempz2(i,j,k) = jacobianl * (sigma_xz*etaxl + sigma_yz*etayl + sigma_zz*etazl)
+
+            tempx3(i,j,k) = jacobianl * (sigma_xx*gammaxl + sigma_yx*gammayl + sigma_zx*gammazl)
+            tempy3(i,j,k) = jacobianl * (sigma_xy*gammaxl + sigma_yy*gammayl + sigma_zy*gammazl)
+            tempz3(i,j,k) = jacobianl * (sigma_xz*gammaxl + sigma_yz*gammayl + sigma_zz*gammazl)
+
+          enddo
+        enddo
+      enddo
+
+      ! subroutines adapted from Deville, Fischer and Mund, High-order methods
+      ! for incompressible fluid flow, Cambridge University Press (2002),
+      ! pages 386 and 389 and Figure 8.3.1
+      do j=1,m2
+        do i=1,m1
+          E1_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C1_m1_m2_5points(1,j) + &
+                                hprimewgll_xxT(i,2)*C1_m1_m2_5points(2,j) + &
+                                hprimewgll_xxT(i,3)*C1_m1_m2_5points(3,j) + &
+                                hprimewgll_xxT(i,4)*C1_m1_m2_5points(4,j) + &
+                                hprimewgll_xxT(i,5)*C1_m1_m2_5points(5,j)
+
+          E2_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C2_m1_m2_5points(1,j) + &
+                                hprimewgll_xxT(i,2)*C2_m1_m2_5points(2,j) + &
+                                hprimewgll_xxT(i,3)*C2_m1_m2_5points(3,j) + &
+                                hprimewgll_xxT(i,4)*C2_m1_m2_5points(4,j) + &
+                                hprimewgll_xxT(i,5)*C2_m1_m2_5points(5,j)
+
+          E3_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C3_m1_m2_5points(1,j) + &
+                                hprimewgll_xxT(i,2)*C3_m1_m2_5points(2,j) + &
+                                hprimewgll_xxT(i,3)*C3_m1_m2_5points(3,j) + &
+                                hprimewgll_xxT(i,4)*C3_m1_m2_5points(4,j) + &
+                                hprimewgll_xxT(i,5)*C3_m1_m2_5points(5,j)
+        enddo
+      enddo
+      do i=1,m1
+        do j=1,m1
+          ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
+          do k = 1,NGLLX
+            newtempx2(i,j,k) = tempx2(i,1,k)*hprimewgll_xx(1,j) + &
+                             tempx2(i,2,k)*hprimewgll_xx(2,j) + &
+                             tempx2(i,3,k)*hprimewgll_xx(3,j) + &
+                             tempx2(i,4,k)*hprimewgll_xx(4,j) + &
+                             tempx2(i,5,k)*hprimewgll_xx(5,j)
+
+            newtempy2(i,j,k) = tempy2(i,1,k)*hprimewgll_xx(1,j) + &
+                             tempy2(i,2,k)*hprimewgll_xx(2,j) + &
+                             tempy2(i,3,k)*hprimewgll_xx(3,j) + &
+                             tempy2(i,4,k)*hprimewgll_xx(4,j) + &
+                             tempy2(i,5,k)*hprimewgll_xx(5,j)
+
+            newtempz2(i,j,k) = tempz2(i,1,k)*hprimewgll_xx(1,j) + &
+                             tempz2(i,2,k)*hprimewgll_xx(2,j) + &
+                             tempz2(i,3,k)*hprimewgll_xx(3,j) + &
+                             tempz2(i,4,k)*hprimewgll_xx(4,j) + &
+                             tempz2(i,5,k)*hprimewgll_xx(5,j)
+          enddo
+        enddo
+      enddo
+      do j=1,m1
+        do i=1,m2
+          E1_mxm_m2_m1_5points(i,j) = C1_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
+                                    C1_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
+                                    C1_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
+                                    C1_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
+                                    C1_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
+
+          E2_mxm_m2_m1_5points(i,j) = C2_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
+                                    C2_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
+                                    C2_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
+                                    C2_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
+                                    C2_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
+
+          E3_mxm_m2_m1_5points(i,j) = C3_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
+                                    C3_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
+                                    C3_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
+                                    C3_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
+                                    C3_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
+        enddo
+      enddo
+
+      do k=1,NGLLZ
+        do j=1,NGLLY
+          fac1 = wgllwgll_yz(j,k)
+          do i=1,NGLLX
+            fac2 = wgllwgll_xz(i,k)
+            fac3 = wgllwgll_xy(i,j)
+
+            ! sum contributions
+            sum_terms(1,i,j,k) = - (fac1*newtempx1(i,j,k) + fac2*newtempx2(i,j,k) + fac3*newtempx3(i,j,k))
+            sum_terms(2,i,j,k) = - (fac1*newtempy1(i,j,k) + fac2*newtempy2(i,j,k) + fac3*newtempy3(i,j,k))
+            sum_terms(3,i,j,k) = - (fac1*newtempz1(i,j,k) + fac2*newtempz2(i,j,k) + fac3*newtempz3(i,j,k))
+
+            if(GRAVITY_VAL) sum_terms(:,i,j,k) = sum_terms(:,i,j,k) + rho_s_H(:,i,j,k)
+
+          enddo
+        enddo
+      enddo
+
+      ! sum contributions from each element to the global mesh and add gravity terms
+      do k=1,NGLLZ
+        do j=1,NGLLY
+#ifdef _HANDOPT        
+! way 2:
+          iglobv5(:) = ibool(:,j,k,ispec)
+
+          accel_inner_core(:,iglobv5(1)) = accel_inner_core(:,iglobv5(1)) + sum_terms(:,1,j,k)
+          accel_inner_core(:,iglobv5(2)) = accel_inner_core(:,iglobv5(2)) + sum_terms(:,2,j,k)
+          accel_inner_core(:,iglobv5(3)) = accel_inner_core(:,iglobv5(3)) + sum_terms(:,3,j,k)
+          accel_inner_core(:,iglobv5(4)) = accel_inner_core(:,iglobv5(4)) + sum_terms(:,4,j,k)
+          accel_inner_core(:,iglobv5(5)) = accel_inner_core(:,iglobv5(5)) + sum_terms(:,5,j,k)
+          
+#else        
+! way 1:
+          do i=1,NGLLX
+            iglob1 = ibool(i,j,k,ispec)
+            accel_inner_core(:,iglob1) = accel_inner_core(:,iglob1) + sum_terms(:,i,j,k)
+          enddo
+#endif
+        enddo
+      enddo
+
+      ! use Runge-Kutta scheme to march memory variables in time
+      ! convention for attenuation
+      ! term in xx = 1
+      ! term in yy = 2
+      ! term in xy = 3
+      ! term in xz = 4
+      ! term in yz = 5
+      ! term in zz not computed since zero trace
+      ! This is because we only implement Q_\mu attenuation and not Q_\kappa.
+      ! Note that this does *NOT* imply that there is no attenuation for P waves
+      ! because for Q_\kappa = infinity one gets (see for instance Dahlen and Tromp (1998)
+      ! equation (9.59) page 350): Q_\alpha = Q_\mu * 3 * (V_p/V_s)^2 / 4
+      ! therefore Q_\alpha is not zero; for instance for V_p / V_s = sqrt(3)
+      ! we get Q_\alpha = (9 / 4) * Q_\mu = 2.25 * Q_\mu
+      if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. ) ) then
+              
+        ! updates R_memory
+        call compute_element_att_memory_ic(ispec,R_memory, &
+                                      vx,vy,vz,vnspec,factor_common, &
+                                      alphaval,betaval,gammaval, &
+                                      muvstore, &
+                                      epsilondev,epsilondev_loc)
+      
+      endif
+
+      ! save deviatoric strain for Runge-Kutta scheme
+      if(COMPUTE_AND_STORE_STRAIN) then
+        epsilondev(:,:,:,:,ispec) = epsilondev_loc(:,:,:,:)
+      endif
+
+    endif   ! end test to exclude fictitious elements in central cube
+
+  enddo ! spectral element loop
+
+  end subroutine compute_forces_inner_core_Dev
+

Deleted: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/compute_forces_inner_core_Dev.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -1,885 +0,0 @@
-!=====================================================================
-!
-!          S p e c f e m 3 D  G l o b e  V e r s i o n  5 . 1
-!          --------------------------------------------------
-!
-!          Main authors: Dimitri Komatitsch and Jeroen Tromp
-!                        Princeton University, USA
-!             and University of Pau / CNRS / INRIA, France
-! (c) Princeton University / California Institute of Technology and University of Pau / CNRS / INRIA
-!                            April 2011
-!
-! This program is free software; you can redistribute it and/or modify
-! it under the terms of the GNU General Public License as published by
-! the Free Software Foundation; either version 2 of the License, or
-! (at your option) any later version.
-!
-! This program is distributed in the hope that it will be useful,
-! but WITHOUT ANY WARRANTY; without even the implied warranty of
-! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-! GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along
-! with this program; if not, write to the Free Software Foundation, Inc.,
-! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-!
-!=====================================================================
-
-  subroutine compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_inner_core,accel_inner_core,xstore,ystore,zstore, &
-          xix,xiy,xiz,etax,etay,etaz,gammax,gammay,gammaz, &
-!----------------------
-            is_on_a_slice_edge_inner_core,icall, &
-            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_INNER_CORE,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore,muvstore,ibool,idoubling, &
-          c11store,c33store,c12store,c13store,c44store,R_memory,epsilondev,epsilon_trace_over_3,&
-          one_minus_sum_beta,alphaval,betaval,gammaval,factor_common, &
-          vx,vy,vz,vnspec)
-
-! this routine is optimized for NGLLX = NGLLY = NGLLZ = 5 using the Deville et al. (2002) inlined matrix-matrix products
-
-  implicit none
-
-  include "constants.h"
-
-! include values created by the mesher
-! done for performance only using static allocation to allow for loop unrolling
-  include "OUTPUT_FILES/values_from_mesher.h"
-
-  ! displacement and acceleration
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: displ_inner_core,accel_inner_core
-  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool
-
-  real(kind=CUSTOM_REAL), dimension(NGLOB_INNER_CORE) :: xstore,ystore,zstore
-
-  ! arrays with mesh parameters per slice
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: xix,xiy,xiz, &
-                      etax,etay,etaz,gammax,gammay,gammaz
-
-  ! for attenuation
-  ! memory variables R_ij are stored at the local rather than global level
-  ! to allow for optimization of cache access by compiler
-  ! variable lengths for factor_common and one_minus_sum_beta
-  integer vx, vy, vz, vnspec
-  real(kind=CUSTOM_REAL), dimension(N_SLS, vx, vy, vz, vnspec) :: factor_common
-  real(kind=CUSTOM_REAL), dimension(vx, vy, vz, vnspec) :: one_minus_sum_beta
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX, NGLLY, NGLLZ) :: factor_common_use
-  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval,betaval,gammaval
-
-  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ATTENUATION) :: R_memory
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: epsilondev
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: epsilon_trace_over_3
-
-  ! array with derivatives of Lagrange polynomials and precalculated products
-  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xx,hprimewgll_xx
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xxT,hprimewgll_xxT
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY) :: wgllwgll_xy
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ) :: wgllwgll_xz
-  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ) :: wgllwgll_yz
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: kappavstore,muvstore
-
-!  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: &
-!    c11store,c33store,c12store,c13store,c44store
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_IC) :: &
-    c11store,c33store,c12store,c13store,c44store
-
-  ! array with the local to global mapping per slice
-  integer, dimension(NSPEC_INNER_CORE) :: idoubling
-
-  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table,density_table,minus_deriv_gravity_table
-
-! local parameters
-  ! Deville
-  ! manually inline the calls to the Deville et al. (2002) routines
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: &
-    tempx1,tempx2,tempx3,tempy1,tempy2,tempy3,tempz1,tempz2,tempz3
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ) :: dummyx_loc,dummyy_loc,dummyz_loc, &
-    newtempx1,newtempx2,newtempx3,newtempy1,newtempy2,newtempy3,newtempz1,newtempz2,newtempz3
-  real(kind=CUSTOM_REAL), dimension(NGLLX,m2) :: B1_m1_m2_5points,B2_m1_m2_5points,B3_m1_m2_5points
-  real(kind=CUSTOM_REAL), dimension(m1,m2) :: C1_m1_m2_5points,C2_m1_m2_5points,C3_m1_m2_5points
-  real(kind=CUSTOM_REAL), dimension(m1,m2) :: E1_m1_m2_5points,E2_m1_m2_5points,E3_m1_m2_5points
-
-  equivalence(dummyx_loc,B1_m1_m2_5points)
-  equivalence(dummyy_loc,B2_m1_m2_5points)
-  equivalence(dummyz_loc,B3_m1_m2_5points)
-  equivalence(tempx1,C1_m1_m2_5points)
-  equivalence(tempy1,C2_m1_m2_5points)
-  equivalence(tempz1,C3_m1_m2_5points)
-  equivalence(newtempx1,E1_m1_m2_5points)
-  equivalence(newtempy1,E2_m1_m2_5points)
-  equivalence(newtempz1,E3_m1_m2_5points)
-
-  real(kind=CUSTOM_REAL), dimension(m2,NGLLX) :: &
-    A1_mxm_m2_m1_5points,A2_mxm_m2_m1_5points,A3_mxm_m2_m1_5points
-  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
-    C1_mxm_m2_m1_5points,C2_mxm_m2_m1_5points,C3_mxm_m2_m1_5points
-  real(kind=CUSTOM_REAL), dimension(m2,m1) :: &
-    E1_mxm_m2_m1_5points,E2_mxm_m2_m1_5points,E3_mxm_m2_m1_5points
-
-  equivalence(dummyx_loc,A1_mxm_m2_m1_5points)
-  equivalence(dummyy_loc,A2_mxm_m2_m1_5points)
-  equivalence(dummyz_loc,A3_mxm_m2_m1_5points)
-  equivalence(tempx3,C1_mxm_m2_m1_5points)
-  equivalence(tempy3,C2_mxm_m2_m1_5points)
-  equivalence(tempz3,C3_mxm_m2_m1_5points)
-  equivalence(newtempx3,E1_mxm_m2_m1_5points)
-  equivalence(newtempy3,E2_mxm_m2_m1_5points)
-  equivalence(newtempz3,E3_mxm_m2_m1_5points)
-
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: sum_terms
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ) :: epsilondev_loc
-  real(kind=CUSTOM_REAL) R_xx_val1,R_yy_val1,R_xx_val2,R_yy_val2,R_xx_val3,R_yy_val3
-
-  real(kind=CUSTOM_REAL) xixl,xiyl,xizl,etaxl,etayl,etazl,gammaxl,gammayl,gammazl,jacobianl
-  real(kind=CUSTOM_REAL) duxdxl,duxdyl,duxdzl,duydxl,duydyl,duydzl,duzdxl,duzdyl,duzdzl
-
-  real(kind=CUSTOM_REAL) duxdxl_plus_duydyl,duxdxl_plus_duzdzl,duydyl_plus_duzdzl
-  real(kind=CUSTOM_REAL) duxdyl_plus_duydxl,duzdxl_plus_duxdzl,duzdyl_plus_duydzl
-
-  real(kind=CUSTOM_REAL) sigma_xx,sigma_yy,sigma_zz,sigma_xy,sigma_xz,sigma_yz
-
-  real(kind=CUSTOM_REAL) fac1,fac2,fac3,templ
-  real(kind=CUSTOM_REAL) lambdal,mul,lambdalplus2mul
-  real(kind=CUSTOM_REAL) kappal
-
-  real(kind=CUSTOM_REAL) minus_sum_beta
-  real(kind=CUSTOM_REAL) c11l,c33l,c12l,c13l,c44l
-
-  ! for gravity
-  double precision radius,rho,minus_g,minus_dg
-  double precision minus_g_over_radius,minus_dg_plus_g_over_radius
-  double precision cos_theta,sin_theta,cos_phi,sin_phi
-  double precision cos_theta_sq,sin_theta_sq,cos_phi_sq,sin_phi_sq
-  double precision theta,phi,factor,gxl,gyl,gzl,sx_l,sy_l,sz_l
-  double precision Hxxl,Hyyl,Hzzl,Hxyl,Hxzl,Hyzl
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NGLLZ) :: rho_s_H
-  real(kind=CUSTOM_REAL) sigma_yx,sigma_zx,sigma_zy
-
-  integer :: int_radius
-  integer :: ispec,ispec_strain
-  integer :: i,j,k !,l
-  integer :: i_SLS,i_memory,imodulo_N_SLS
-  integer :: iglob1,iglob2,iglob3,iglob4,iglob5
-
-! this for non blocking MPI
-  integer :: iphase,icall
-
-  integer :: computed_elements
-
-  logical, dimension(NSPEC_INNER_CORE) :: is_on_a_slice_edge_inner_core
-
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: accel_crust_mantle
-
-  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool_inner_core
-
-  integer, dimension(NSPEC_INNER_CORE) :: idoubling_inner_core
-
-  integer :: ichunk,iproc_xi,iproc_eta,myrank
-
-  integer, dimension(NCHUNKS_VAL,0:NPROC_XI_VAL-1,0:NPROC_ETA_VAL-1) :: addressing
-
-  integer, dimension(NGLOB2DMAX_XMIN_XMAX_CM) :: iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle
-  integer, dimension(NGLOB2DMAX_YMIN_YMAX_CM) :: iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle
-
-  integer, dimension(NGLOB2DMAX_XMIN_XMAX_IC) :: iboolleft_xi_inner_core,iboolright_xi_inner_core
-  integer, dimension(NGLOB2DMAX_YMIN_YMAX_IC) :: iboolleft_eta_inner_core,iboolright_eta_inner_core
-
-  integer npoin2D_faces_crust_mantle(NUMFACES_SHARED)
-  integer npoin2D_faces_inner_core(NUMFACES_SHARED)
-
-  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-       npoin2D_xi_inner_core,npoin2D_eta_inner_core
-
-! communication pattern for faces between chunks
-  integer, dimension(NUMMSGS_FACES_VAL) :: iprocfrom_faces,iprocto_faces
-
-! communication pattern for corners between chunks
-  integer, dimension(NCORNERSCHUNKS_VAL) :: iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners
-
-  integer, dimension(NGLOB1D_RADIAL_CM,NUMCORNERS_SHARED) :: iboolcorner_crust_mantle
-  integer, dimension(NGLOB1D_RADIAL_IC,NUMCORNERS_SHARED) :: iboolcorner_inner_core
-
-  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_crust_mantle
-  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_inner_core
-
-  integer :: npoin2D_max_all_CM_IC
-  real(kind=CUSTOM_REAL), dimension(NDIM,npoin2D_max_all_CM_IC) :: buffer_send_faces,buffer_received_faces
-
-! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB1D_RADIAL_CM + NGLOB1D_RADIAL_IC) :: &
-     buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector
-
-! for matching with central cube in inner core
-  integer nb_msgs_theor_in_cube, npoin2D_cube_from_slices,iphase_CC
-  integer, dimension(nb_msgs_theor_in_cube) :: sender_from_slices_to_cube
-  double precision, dimension(npoin2D_cube_from_slices,NDIM) :: buffer_slices
-  double precision, dimension(npoin2D_cube_from_slices,NDIM,nb_msgs_theor_in_cube) :: buffer_all_cube_from_slices
-  integer, dimension(nb_msgs_theor_in_cube,npoin2D_cube_from_slices):: ibool_central_cube
-  integer receiver_cube_from_slices
-  logical :: INCLUDE_CENTRAL_CUBE
-
-! local to global mapping
-  integer NSPEC2D_BOTTOM_INNER_CORE
-  integer, dimension(NSPEC2D_BOTTOM_INNER_CORE) :: ibelm_bottom_inner_core
-
-! ****************************************************
-!   big loop over all spectral elements in the solid
-! ****************************************************
-
-  imodulo_N_SLS = mod(N_SLS,3)
-
-  computed_elements = 0
-
-  do ispec = 1,NSPEC_INNER_CORE
-
-! hide communications by computing the edges first
-    if((icall == 2 .and. is_on_a_slice_edge_inner_core(ispec)) .or. &
-       (icall == 1 .and. .not. is_on_a_slice_edge_inner_core(ispec))) cycle
-
-    ! exclude fictitious elements in central cube
-    if(idoubling(ispec) /= IFLAG_IN_FICTITIOUS_CUBE) then
-
-! process the communications every ELEMENTS_NONBLOCKING elements
-    computed_elements = computed_elements + 1
-    if (USE_NONBLOCKING_COMMS .and. icall == 2 .and. mod(computed_elements,ELEMENTS_NONBLOCKING_CM_IC) == 0) then
-
-      if(iphase <= 7) call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES_VAL,NCORNERSCHUNKS_VAL, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL_CM, &
-            NGLOB1D_RADIAL_IC,NCHUNKS_VAL,iphase)
-
-      if(INCLUDE_CENTRAL_CUBE) then
-          if(iphase > 7 .and. iphase_CC <= 4) &
-            call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-                   npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-                   receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
-                   ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,accel_inner_core,NDIM,iphase_CC)
-      endif
-
-    endif
-
-      ! subroutines adapted from Deville, Fischer and Mund, High-order methods
-      ! for incompressible fluid flow, Cambridge University Press (2002),
-      ! pages 386 and 389 and Figure 8.3.1
-      do k=1,NGLLZ
-        do j=1,NGLLY
-! way 1:
-!          do i=1,NGLLX
-!              iglob = ibool(i,j,k,ispec)
-!              dummyx_loc(i,j,k) = displ_inner_core(1,iglob)
-!              dummyy_loc(i,j,k) = displ_inner_core(2,iglob)
-!              dummyz_loc(i,j,k) = displ_inner_core(3,iglob)
-!          enddo
-
-! way 2:
-        ! since we know that NGLLX = 5, this should help pipelining
-        iglob1 = ibool(1,j,k,ispec)
-        iglob2 = ibool(2,j,k,ispec)
-        iglob3 = ibool(3,j,k,ispec)
-        iglob4 = ibool(4,j,k,ispec)
-        iglob5 = ibool(5,j,k,ispec)
-
-        dummyx_loc(1,j,k) = displ_inner_core(1,iglob1)
-        dummyy_loc(1,j,k) = displ_inner_core(2,iglob1)
-        dummyz_loc(1,j,k) = displ_inner_core(3,iglob1)
-
-        dummyx_loc(2,j,k) = displ_inner_core(1,iglob2)
-        dummyy_loc(2,j,k) = displ_inner_core(2,iglob2)
-        dummyz_loc(2,j,k) = displ_inner_core(3,iglob2)
-
-        dummyx_loc(3,j,k) = displ_inner_core(1,iglob3)
-        dummyy_loc(3,j,k) = displ_inner_core(2,iglob3)
-        dummyz_loc(3,j,k) = displ_inner_core(3,iglob3)
-
-        dummyx_loc(4,j,k) = displ_inner_core(1,iglob4)
-        dummyy_loc(4,j,k) = displ_inner_core(2,iglob4)
-        dummyz_loc(4,j,k) = displ_inner_core(3,iglob4)
-
-        dummyx_loc(5,j,k) = displ_inner_core(1,iglob5)
-        dummyy_loc(5,j,k) = displ_inner_core(2,iglob5)
-        dummyz_loc(5,j,k) = displ_inner_core(3,iglob5)
-
-
-        enddo
-      enddo
-      do j=1,m2
-        do i=1,m1
-          C1_m1_m2_5points(i,j) = hprime_xx(i,1)*B1_m1_m2_5points(1,j) + &
-                                hprime_xx(i,2)*B1_m1_m2_5points(2,j) + &
-                                hprime_xx(i,3)*B1_m1_m2_5points(3,j) + &
-                                hprime_xx(i,4)*B1_m1_m2_5points(4,j) + &
-                                hprime_xx(i,5)*B1_m1_m2_5points(5,j)
-
-          C2_m1_m2_5points(i,j) = hprime_xx(i,1)*B2_m1_m2_5points(1,j) + &
-                                hprime_xx(i,2)*B2_m1_m2_5points(2,j) + &
-                                hprime_xx(i,3)*B2_m1_m2_5points(3,j) + &
-                                hprime_xx(i,4)*B2_m1_m2_5points(4,j) + &
-                                hprime_xx(i,5)*B2_m1_m2_5points(5,j)
-
-          C3_m1_m2_5points(i,j) = hprime_xx(i,1)*B3_m1_m2_5points(1,j) + &
-                                hprime_xx(i,2)*B3_m1_m2_5points(2,j) + &
-                                hprime_xx(i,3)*B3_m1_m2_5points(3,j) + &
-                                hprime_xx(i,4)*B3_m1_m2_5points(4,j) + &
-                                hprime_xx(i,5)*B3_m1_m2_5points(5,j)
-        enddo
-      enddo
-      do j=1,m1
-        do i=1,m1
-          ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
-          do k = 1,NGLLX
-            tempx2(i,j,k) = dummyx_loc(i,1,k)*hprime_xxT(1,j) + &
-                          dummyx_loc(i,2,k)*hprime_xxT(2,j) + &
-                          dummyx_loc(i,3,k)*hprime_xxT(3,j) + &
-                          dummyx_loc(i,4,k)*hprime_xxT(4,j) + &
-                          dummyx_loc(i,5,k)*hprime_xxT(5,j)
-
-            tempy2(i,j,k) = dummyy_loc(i,1,k)*hprime_xxT(1,j) + &
-                          dummyy_loc(i,2,k)*hprime_xxT(2,j) + &
-                          dummyy_loc(i,3,k)*hprime_xxT(3,j) + &
-                          dummyy_loc(i,4,k)*hprime_xxT(4,j) + &
-                          dummyy_loc(i,5,k)*hprime_xxT(5,j)
-
-            tempz2(i,j,k) = dummyz_loc(i,1,k)*hprime_xxT(1,j) + &
-                          dummyz_loc(i,2,k)*hprime_xxT(2,j) + &
-                          dummyz_loc(i,3,k)*hprime_xxT(3,j) + &
-                          dummyz_loc(i,4,k)*hprime_xxT(4,j) + &
-                          dummyz_loc(i,5,k)*hprime_xxT(5,j)
-          enddo
-        enddo
-      enddo
-      do j=1,m1
-        do i=1,m2
-          C1_mxm_m2_m1_5points(i,j) = A1_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
-                                    A1_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
-                                    A1_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
-                                    A1_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
-                                    A1_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
-
-          C2_mxm_m2_m1_5points(i,j) = A2_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
-                                    A2_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
-                                    A2_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
-                                    A2_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
-                                    A2_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
-
-          C3_mxm_m2_m1_5points(i,j) = A3_mxm_m2_m1_5points(i,1)*hprime_xxT(1,j) + &
-                                    A3_mxm_m2_m1_5points(i,2)*hprime_xxT(2,j) + &
-                                    A3_mxm_m2_m1_5points(i,3)*hprime_xxT(3,j) + &
-                                    A3_mxm_m2_m1_5points(i,4)*hprime_xxT(4,j) + &
-                                    A3_mxm_m2_m1_5points(i,5)*hprime_xxT(5,j)
-        enddo
-      enddo
-
-      do k=1,NGLLZ
-        do j=1,NGLLY
-          do i=1,NGLLX
-
-            ! get derivatives of ux, uy and uz with respect to x, y and z
-            xixl = xix(i,j,k,ispec)
-            xiyl = xiy(i,j,k,ispec)
-            xizl = xiz(i,j,k,ispec)
-            etaxl = etax(i,j,k,ispec)
-            etayl = etay(i,j,k,ispec)
-            etazl = etaz(i,j,k,ispec)
-            gammaxl = gammax(i,j,k,ispec)
-            gammayl = gammay(i,j,k,ispec)
-            gammazl = gammaz(i,j,k,ispec)
-
-            ! compute the jacobian
-            jacobianl = 1._CUSTOM_REAL / (xixl*(etayl*gammazl-etazl*gammayl) &
-                          - xiyl*(etaxl*gammazl-etazl*gammaxl) &
-                          + xizl*(etaxl*gammayl-etayl*gammaxl))
-
-            duxdxl = xixl*tempx1(i,j,k) + etaxl*tempx2(i,j,k) + gammaxl*tempx3(i,j,k)
-            duxdyl = xiyl*tempx1(i,j,k) + etayl*tempx2(i,j,k) + gammayl*tempx3(i,j,k)
-            duxdzl = xizl*tempx1(i,j,k) + etazl*tempx2(i,j,k) + gammazl*tempx3(i,j,k)
-
-            duydxl = xixl*tempy1(i,j,k) + etaxl*tempy2(i,j,k) + gammaxl*tempy3(i,j,k)
-            duydyl = xiyl*tempy1(i,j,k) + etayl*tempy2(i,j,k) + gammayl*tempy3(i,j,k)
-            duydzl = xizl*tempy1(i,j,k) + etazl*tempy2(i,j,k) + gammazl*tempy3(i,j,k)
-
-            duzdxl = xixl*tempz1(i,j,k) + etaxl*tempz2(i,j,k) + gammaxl*tempz3(i,j,k)
-            duzdyl = xiyl*tempz1(i,j,k) + etayl*tempz2(i,j,k) + gammayl*tempz3(i,j,k)
-            duzdzl = xizl*tempz1(i,j,k) + etazl*tempz2(i,j,k) + gammazl*tempz3(i,j,k)
-
-            ! precompute some sums to save CPU time
-            duxdxl_plus_duydyl = duxdxl + duydyl
-            duxdxl_plus_duzdzl = duxdxl + duzdzl
-            duydyl_plus_duzdzl = duydyl + duzdzl
-            duxdyl_plus_duydxl = duxdyl + duydxl
-            duzdxl_plus_duxdzl = duzdxl + duxdzl
-            duzdyl_plus_duydzl = duzdyl + duydzl
-
-            ! compute deviatoric strain
-            if (COMPUTE_AND_STORE_STRAIN) then
-              if(NSPEC_INNER_CORE_STRAIN_ONLY == 1) then
-                ispec_strain = 1
-              else
-                ispec_strain = ispec
-              endif
-              templ = ONE_THIRD * (duxdxl + duydyl + duzdzl)
-              epsilon_trace_over_3(i,j,k,ispec_strain) = templ
-              epsilondev_loc(1,i,j,k) = duxdxl - templ
-              epsilondev_loc(2,i,j,k) = duydyl - templ
-              epsilondev_loc(3,i,j,k) = 0.5 * duxdyl_plus_duydxl
-              epsilondev_loc(4,i,j,k) = 0.5 * duzdxl_plus_duxdzl
-              epsilondev_loc(5,i,j,k) = 0.5 * duzdyl_plus_duydzl
-            endif
-
-            if(ATTENUATION_VAL) then
-              minus_sum_beta =  one_minus_sum_beta(i,j,k,ispec) - 1.0
-            endif
-
-            if(ANISOTROPIC_INNER_CORE_VAL) then
-              ! elastic tensor for hexagonal symmetry in reduced notation:
-              !
-              !      c11 c12 c13  0   0        0
-              !      c12 c11 c13  0   0        0
-              !      c13 c13 c33  0   0        0
-              !       0   0   0  c44  0        0
-              !       0   0   0   0  c44       0
-              !       0   0   0   0   0  (c11-c12)/2
-              !
-              !       in terms of the A, C, L, N and F of Love (1927):
-              !
-              !       c11 = A
-              !       c12 = A-2N
-              !       c13 = F
-              !       c33 = C
-              !       c44 = L
-              c11l = c11store(i,j,k,ispec)
-              c12l = c12store(i,j,k,ispec)
-              c13l = c13store(i,j,k,ispec)
-              c33l = c33store(i,j,k,ispec)
-              c44l = c44store(i,j,k,ispec)
-
-              ! use unrelaxed parameters if attenuation
-              if(ATTENUATION_VAL) then
-                mul = muvstore(i,j,k,ispec)
-                c11l = c11l + FOUR_THIRDS * minus_sum_beta * mul
-                c12l = c12l - TWO_THIRDS * minus_sum_beta * mul
-                c13l = c13l - TWO_THIRDS * minus_sum_beta * mul
-                c33l = c33l + FOUR_THIRDS * minus_sum_beta * mul
-                c44l = c44l + minus_sum_beta * mul
-              endif
-
-              sigma_xx = c11l*duxdxl + c12l*duydyl + c13l*duzdzl
-              sigma_yy = c12l*duxdxl + c11l*duydyl + c13l*duzdzl
-              sigma_zz = c13l*duxdxl + c13l*duydyl + c33l*duzdzl
-              sigma_xy = 0.5*(c11l-c12l)*duxdyl_plus_duydxl
-              sigma_xz = c44l*duzdxl_plus_duxdzl
-              sigma_yz = c44l*duzdyl_plus_duydzl
-            else
-
-              ! inner core with no anisotropy, use kappav and muv for instance
-              ! layer with no anisotropy, use kappav and muv for instance
-              kappal = kappavstore(i,j,k,ispec)
-              mul = muvstore(i,j,k,ispec)
-
-              ! use unrelaxed parameters if attenuation
-              if(ATTENUATION_VAL) then
-                mul = mul * one_minus_sum_beta(i,j,k,ispec)
-              endif
-
-              lambdalplus2mul = kappal + FOUR_THIRDS * mul
-              lambdal = lambdalplus2mul - 2.*mul
-
-              ! compute stress sigma
-              sigma_xx = lambdalplus2mul*duxdxl + lambdal*duydyl_plus_duzdzl
-              sigma_yy = lambdalplus2mul*duydyl + lambdal*duxdxl_plus_duzdzl
-              sigma_zz = lambdalplus2mul*duzdzl + lambdal*duxdxl_plus_duydyl
-
-              sigma_xy = mul*duxdyl_plus_duydxl
-              sigma_xz = mul*duzdxl_plus_duxdzl
-              sigma_yz = mul*duzdyl_plus_duydzl
-
-            endif
-
-            ! subtract memory variables if attenuation
-            if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. ) ) then
-
-! way 1:
-!              do i_SLS = 1,N_SLS
-!                R_xx_val = R_memory(1,i_SLS,i,j,k,ispec)
-!                R_yy_val = R_memory(2,i_SLS,i,j,k,ispec)
-!                sigma_xx = sigma_xx - R_xx_val
-!                sigma_yy = sigma_yy - R_yy_val
-!                sigma_zz = sigma_zz + R_xx_val + R_yy_val
-!                sigma_xy = sigma_xy - R_memory(3,i_SLS,i,j,k,ispec)
-!                sigma_xz = sigma_xz - R_memory(4,i_SLS,i,j,k,ispec)
-!                sigma_yz = sigma_yz - R_memory(5,i_SLS,i,j,k,ispec)
-!              enddo
-
-! way 2:
-! note: this should help compilers to pipeline the code and make better use of the cache;
-!          depending on compilers, it can further decrease the computation time by ~ 30%.
-!          by default, N_SLS = 3, there for we take steps of 3
-            if(imodulo_N_SLS >= 1) then
-              do i_SLS = 1,imodulo_N_SLS
-                R_xx_val1 = R_memory(1,i_SLS,i,j,k,ispec)
-                R_yy_val1 = R_memory(2,i_SLS,i,j,k,ispec)
-                sigma_xx = sigma_xx - R_xx_val1
-                sigma_yy = sigma_yy - R_yy_val1
-                sigma_zz = sigma_zz + R_xx_val1 + R_yy_val1
-                sigma_xy = sigma_xy - R_memory(3,i_SLS,i,j,k,ispec)
-                sigma_xz = sigma_xz - R_memory(4,i_SLS,i,j,k,ispec)
-                sigma_yz = sigma_yz - R_memory(5,i_SLS,i,j,k,ispec)
-              enddo
-            endif
-
-            if(N_SLS >= imodulo_N_SLS+1) then
-              do i_SLS = imodulo_N_SLS+1,N_SLS,3
-                R_xx_val1 = R_memory(1,i_SLS,i,j,k,ispec)
-                R_yy_val1 = R_memory(2,i_SLS,i,j,k,ispec)
-                sigma_xx = sigma_xx - R_xx_val1
-                sigma_yy = sigma_yy - R_yy_val1
-                sigma_zz = sigma_zz + R_xx_val1 + R_yy_val1
-                sigma_xy = sigma_xy - R_memory(3,i_SLS,i,j,k,ispec)
-                sigma_xz = sigma_xz - R_memory(4,i_SLS,i,j,k,ispec)
-                sigma_yz = sigma_yz - R_memory(5,i_SLS,i,j,k,ispec)
-
-                R_xx_val2 = R_memory(1,i_SLS+1,i,j,k,ispec)
-                R_yy_val2 = R_memory(2,i_SLS+1,i,j,k,ispec)
-                sigma_xx = sigma_xx - R_xx_val2
-                sigma_yy = sigma_yy - R_yy_val2
-                sigma_zz = sigma_zz + R_xx_val2 + R_yy_val2
-                sigma_xy = sigma_xy - R_memory(3,i_SLS+1,i,j,k,ispec)
-                sigma_xz = sigma_xz - R_memory(4,i_SLS+1,i,j,k,ispec)
-                sigma_yz = sigma_yz - R_memory(5,i_SLS+1,i,j,k,ispec)
-
-                R_xx_val3 = R_memory(1,i_SLS+2,i,j,k,ispec)
-                R_yy_val3 = R_memory(2,i_SLS+2,i,j,k,ispec)
-                sigma_xx = sigma_xx - R_xx_val3
-                sigma_yy = sigma_yy - R_yy_val3
-                sigma_zz = sigma_zz + R_xx_val3 + R_yy_val3
-                sigma_xy = sigma_xy - R_memory(3,i_SLS+2,i,j,k,ispec)
-                sigma_xz = sigma_xz - R_memory(4,i_SLS+2,i,j,k,ispec)
-                sigma_yz = sigma_yz - R_memory(5,i_SLS+2,i,j,k,ispec)
-              enddo
-            endif
-
-            endif
-
-            ! define symmetric components of sigma for gravity
-            sigma_yx = sigma_xy
-            sigma_zx = sigma_xz
-            sigma_zy = sigma_yz
-
-            ! compute non-symmetric terms for gravity
-            if(GRAVITY_VAL) then
-
-              ! use mesh coordinates to get theta and phi
-              ! x y and z contain r theta and phi
-              iglob1 = ibool(i,j,k,ispec)
-              radius = dble(xstore(iglob1))
-              theta = dble(ystore(iglob1))
-              phi = dble(zstore(iglob1))
-
-              ! make sure radius is never zero even for points at center of cube
-              ! because we later divide by radius
-              if(radius < 100.d0 / R_EARTH) radius = 100.d0 / R_EARTH
-
-              cos_theta = dcos(theta)
-              sin_theta = dsin(theta)
-              cos_phi = dcos(phi)
-              sin_phi = dsin(phi)
-
-              cos_theta_sq = cos_theta**2
-              sin_theta_sq = sin_theta**2
-              cos_phi_sq = cos_phi**2
-              sin_phi_sq = sin_phi**2
-
-              ! get g, rho and dg/dr=dg
-              ! spherical components of the gravitational acceleration
-              ! for efficiency replace with lookup table every 100 m in radial direction
-              ! make sure we never use zero for point exactly at the center of the Earth
-              int_radius = max(1,nint(radius * R_EARTH_KM * 10.d0))
-              minus_g = minus_gravity_table(int_radius)
-              minus_dg = minus_deriv_gravity_table(int_radius)
-              rho = density_table(int_radius)
-
-              ! Cartesian components of the gravitational acceleration
-              gxl = minus_g*sin_theta*cos_phi
-              gyl = minus_g*sin_theta*sin_phi
-              gzl = minus_g*cos_theta
-
-              ! Cartesian components of gradient of gravitational acceleration
-              ! obtained from spherical components
-              minus_g_over_radius = minus_g / radius
-              minus_dg_plus_g_over_radius = minus_dg - minus_g_over_radius
-
-              Hxxl = minus_g_over_radius*(cos_phi_sq*cos_theta_sq + sin_phi_sq) + cos_phi_sq*minus_dg*sin_theta_sq
-              Hyyl = minus_g_over_radius*(cos_phi_sq + cos_theta_sq*sin_phi_sq) + minus_dg*sin_phi_sq*sin_theta_sq
-              Hzzl = cos_theta_sq*minus_dg + minus_g_over_radius*sin_theta_sq
-              Hxyl = cos_phi*minus_dg_plus_g_over_radius*sin_phi*sin_theta_sq
-              Hxzl = cos_phi*cos_theta*minus_dg_plus_g_over_radius*sin_theta
-              Hyzl = cos_theta*minus_dg_plus_g_over_radius*sin_phi*sin_theta
-
-              ! for locality principle, we set iglob again, in order to have it in the cache again
-              iglob1 = ibool(i,j,k,ispec)
-
-              ! distinguish between single and double precision for reals
-              if(CUSTOM_REAL == SIZE_REAL) then
-                ! get displacement and multiply by density to compute G tensor
-                sx_l = rho * dble(displ_inner_core(1,iglob1))
-                sy_l = rho * dble(displ_inner_core(2,iglob1))
-                sz_l = rho * dble(displ_inner_core(3,iglob1))
-
-                ! compute G tensor from s . g and add to sigma (not symmetric)
-                sigma_xx = sigma_xx + sngl(sy_l*gyl + sz_l*gzl)
-                sigma_yy = sigma_yy + sngl(sx_l*gxl + sz_l*gzl)
-                sigma_zz = sigma_zz + sngl(sx_l*gxl + sy_l*gyl)
-
-                sigma_xy = sigma_xy - sngl(sx_l * gyl)
-                sigma_yx = sigma_yx - sngl(sy_l * gxl)
-
-                sigma_xz = sigma_xz - sngl(sx_l * gzl)
-                sigma_zx = sigma_zx - sngl(sz_l * gxl)
-
-                sigma_yz = sigma_yz - sngl(sy_l * gzl)
-                sigma_zy = sigma_zy - sngl(sz_l * gyl)
-
-                ! precompute vector
-                factor = dble(jacobianl) * wgll_cube(i,j,k)
-                rho_s_H(1,i,j,k) = sngl(factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl))
-                rho_s_H(2,i,j,k) = sngl(factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl))
-                rho_s_H(3,i,j,k) = sngl(factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl))
-
-              else
-
-                ! get displacement and multiply by density to compute G tensor
-                sx_l = rho * displ_inner_core(1,iglob1)
-                sy_l = rho * displ_inner_core(2,iglob1)
-                sz_l = rho * displ_inner_core(3,iglob1)
-
-                ! compute G tensor from s . g and add to sigma (not symmetric)
-                sigma_xx = sigma_xx + sy_l*gyl + sz_l*gzl
-                sigma_yy = sigma_yy + sx_l*gxl + sz_l*gzl
-                sigma_zz = sigma_zz + sx_l*gxl + sy_l*gyl
-
-                sigma_xy = sigma_xy - sx_l * gyl
-                sigma_yx = sigma_yx - sy_l * gxl
-
-                sigma_xz = sigma_xz - sx_l * gzl
-                sigma_zx = sigma_zx - sz_l * gxl
-
-                sigma_yz = sigma_yz - sy_l * gzl
-                sigma_zy = sigma_zy - sz_l * gyl
-
-                ! precompute vector
-                factor = jacobianl * wgll_cube(i,j,k)
-                rho_s_H(1,i,j,k) = factor * (sx_l * Hxxl + sy_l * Hxyl + sz_l * Hxzl)
-                rho_s_H(2,i,j,k) = factor * (sx_l * Hxyl + sy_l * Hyyl + sz_l * Hyzl)
-                rho_s_H(3,i,j,k) = factor * (sx_l * Hxzl + sy_l * Hyzl + sz_l * Hzzl)
-
-              endif
-
-            endif  ! end of section with gravity terms
-
-            ! form dot product with test vector, non-symmetric form
-            tempx1(i,j,k) = jacobianl * (sigma_xx*xixl + sigma_yx*xiyl + sigma_zx*xizl)
-            tempy1(i,j,k) = jacobianl * (sigma_xy*xixl + sigma_yy*xiyl + sigma_zy*xizl)
-            tempz1(i,j,k) = jacobianl * (sigma_xz*xixl + sigma_yz*xiyl + sigma_zz*xizl)
-
-            tempx2(i,j,k) = jacobianl * (sigma_xx*etaxl + sigma_yx*etayl + sigma_zx*etazl)
-            tempy2(i,j,k) = jacobianl * (sigma_xy*etaxl + sigma_yy*etayl + sigma_zy*etazl)
-            tempz2(i,j,k) = jacobianl * (sigma_xz*etaxl + sigma_yz*etayl + sigma_zz*etazl)
-
-            tempx3(i,j,k) = jacobianl * (sigma_xx*gammaxl + sigma_yx*gammayl + sigma_zx*gammazl)
-            tempy3(i,j,k) = jacobianl * (sigma_xy*gammaxl + sigma_yy*gammayl + sigma_zy*gammazl)
-            tempz3(i,j,k) = jacobianl * (sigma_xz*gammaxl + sigma_yz*gammayl + sigma_zz*gammazl)
-
-          enddo
-        enddo
-      enddo
-
-      ! subroutines adapted from Deville, Fischer and Mund, High-order methods
-      ! for incompressible fluid flow, Cambridge University Press (2002),
-      ! pages 386 and 389 and Figure 8.3.1
-      do j=1,m2
-        do i=1,m1
-          E1_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C1_m1_m2_5points(1,j) + &
-                                hprimewgll_xxT(i,2)*C1_m1_m2_5points(2,j) + &
-                                hprimewgll_xxT(i,3)*C1_m1_m2_5points(3,j) + &
-                                hprimewgll_xxT(i,4)*C1_m1_m2_5points(4,j) + &
-                                hprimewgll_xxT(i,5)*C1_m1_m2_5points(5,j)
-
-          E2_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C2_m1_m2_5points(1,j) + &
-                                hprimewgll_xxT(i,2)*C2_m1_m2_5points(2,j) + &
-                                hprimewgll_xxT(i,3)*C2_m1_m2_5points(3,j) + &
-                                hprimewgll_xxT(i,4)*C2_m1_m2_5points(4,j) + &
-                                hprimewgll_xxT(i,5)*C2_m1_m2_5points(5,j)
-
-          E3_m1_m2_5points(i,j) = hprimewgll_xxT(i,1)*C3_m1_m2_5points(1,j) + &
-                                hprimewgll_xxT(i,2)*C3_m1_m2_5points(2,j) + &
-                                hprimewgll_xxT(i,3)*C3_m1_m2_5points(3,j) + &
-                                hprimewgll_xxT(i,4)*C3_m1_m2_5points(4,j) + &
-                                hprimewgll_xxT(i,5)*C3_m1_m2_5points(5,j)
-        enddo
-      enddo
-      do i=1,m1
-        do j=1,m1
-          ! for efficiency it is better to leave this loop on k inside, it leads to slightly faster code
-          do k = 1,NGLLX
-            newtempx2(i,j,k) = tempx2(i,1,k)*hprimewgll_xx(1,j) + &
-                             tempx2(i,2,k)*hprimewgll_xx(2,j) + &
-                             tempx2(i,3,k)*hprimewgll_xx(3,j) + &
-                             tempx2(i,4,k)*hprimewgll_xx(4,j) + &
-                             tempx2(i,5,k)*hprimewgll_xx(5,j)
-
-            newtempy2(i,j,k) = tempy2(i,1,k)*hprimewgll_xx(1,j) + &
-                             tempy2(i,2,k)*hprimewgll_xx(2,j) + &
-                             tempy2(i,3,k)*hprimewgll_xx(3,j) + &
-                             tempy2(i,4,k)*hprimewgll_xx(4,j) + &
-                             tempy2(i,5,k)*hprimewgll_xx(5,j)
-
-            newtempz2(i,j,k) = tempz2(i,1,k)*hprimewgll_xx(1,j) + &
-                             tempz2(i,2,k)*hprimewgll_xx(2,j) + &
-                             tempz2(i,3,k)*hprimewgll_xx(3,j) + &
-                             tempz2(i,4,k)*hprimewgll_xx(4,j) + &
-                             tempz2(i,5,k)*hprimewgll_xx(5,j)
-          enddo
-        enddo
-      enddo
-      do j=1,m1
-        do i=1,m2
-          E1_mxm_m2_m1_5points(i,j) = C1_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
-                                    C1_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
-                                    C1_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
-                                    C1_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
-                                    C1_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
-
-          E2_mxm_m2_m1_5points(i,j) = C2_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
-                                    C2_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
-                                    C2_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
-                                    C2_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
-                                    C2_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
-
-          E3_mxm_m2_m1_5points(i,j) = C3_mxm_m2_m1_5points(i,1)*hprimewgll_xx(1,j) + &
-                                    C3_mxm_m2_m1_5points(i,2)*hprimewgll_xx(2,j) + &
-                                    C3_mxm_m2_m1_5points(i,3)*hprimewgll_xx(3,j) + &
-                                    C3_mxm_m2_m1_5points(i,4)*hprimewgll_xx(4,j) + &
-                                    C3_mxm_m2_m1_5points(i,5)*hprimewgll_xx(5,j)
-        enddo
-      enddo
-
-      do k=1,NGLLZ
-        do j=1,NGLLY
-          do i=1,NGLLX
-            fac1 = wgllwgll_yz(j,k)
-            fac2 = wgllwgll_xz(i,k)
-            fac3 = wgllwgll_xy(i,j)
-
-            ! sum contributions
-            sum_terms(1,i,j,k) = - (fac1*newtempx1(i,j,k) + fac2*newtempx2(i,j,k) + fac3*newtempx3(i,j,k))
-            sum_terms(2,i,j,k) = - (fac1*newtempy1(i,j,k) + fac2*newtempy2(i,j,k) + fac3*newtempy3(i,j,k))
-            sum_terms(3,i,j,k) = - (fac1*newtempz1(i,j,k) + fac2*newtempz2(i,j,k) + fac3*newtempz3(i,j,k))
-
-            if(GRAVITY_VAL) sum_terms(:,i,j,k) = sum_terms(:,i,j,k) + rho_s_H(:,i,j,k)
-
-          enddo
-        enddo
-      enddo
-
-      ! sum contributions from each element to the global mesh and add gravity terms
-      do k=1,NGLLZ
-        do j=1,NGLLY
-! way 1:
-!          do i=1,NGLLX
-!            iglob = ibool(i,j,k,ispec)
-!            accel_inner_core(:,iglob) = accel_inner_core(:,iglob) + sum_terms(:,i,j,k)
-!          enddo
-
-! way 2:
-          accel_inner_core(:,ibool(1,j,k,ispec)) = accel_inner_core(:,ibool(1,j,k,ispec)) + sum_terms(:,1,j,k)
-          accel_inner_core(:,ibool(2,j,k,ispec)) = accel_inner_core(:,ibool(2,j,k,ispec)) + sum_terms(:,2,j,k)
-          accel_inner_core(:,ibool(3,j,k,ispec)) = accel_inner_core(:,ibool(3,j,k,ispec)) + sum_terms(:,3,j,k)
-          accel_inner_core(:,ibool(4,j,k,ispec)) = accel_inner_core(:,ibool(4,j,k,ispec)) + sum_terms(:,4,j,k)
-          accel_inner_core(:,ibool(5,j,k,ispec)) = accel_inner_core(:,ibool(5,j,k,ispec)) + sum_terms(:,5,j,k)
-
-        enddo
-      enddo
-
-      ! use Runge-Kutta scheme to march memory variables in time
-      ! convention for attenuation
-      ! term in xx = 1
-      ! term in yy = 2
-      ! term in xy = 3
-      ! term in xz = 4
-      ! term in yz = 5
-      ! term in zz not computed since zero trace
-      ! This is because we only implement Q_\mu attenuation and not Q_\kappa.
-      ! Note that this does *NOT* imply that there is no attenuation for P waves
-      ! because for Q_\kappa = infinity one gets (see for instance Dahlen and Tromp (1998)
-      ! equation (9.59) page 350): Q_\alpha = Q_\mu * 3 * (V_p/V_s)^2 / 4
-      ! therefore Q_\alpha is not zero; for instance for V_p / V_s = sqrt(3)
-      ! we get Q_\alpha = (9 / 4) * Q_\mu = 2.25 * Q_\mu
-      if(ATTENUATION_VAL .and. ( USE_ATTENUATION_MIMIC .eqv. .false. ) ) then
-        do i_SLS = 1,N_SLS
-          factor_common_use = factor_common(i_SLS,:,:,:,ispec)
-          do i_memory = 1,5
-             R_memory(i_memory,i_SLS,:,:,:,ispec) = &
-                  alphaval(i_SLS) * &
-                  R_memory(i_memory,i_SLS,:,:,:,ispec) + muvstore(:,:,:,ispec) * &
-                  factor_common_use * &
-                  (betaval(i_SLS) * &
-                  epsilondev(i_memory,:,:,:,ispec) + gammaval(i_SLS) * epsilondev_loc(i_memory,:,:,:))
-          enddo
-        enddo
-
-      endif
-
-      ! save deviatoric strain for Runge-Kutta scheme
-      if(COMPUTE_AND_STORE_STRAIN) then
-! way 1:
-        !epsilondev(:,:,:,:,ispec) = epsilondev_loc(:,:,:,:)
-! way 2:
-        do k=1,NGLLZ
-          do j=1,NGLLY
-              !dummy(:) = epsilondev_loc(:,1,j,k)
-
-              epsilondev(:,1,j,k,ispec) = epsilondev_loc(:,1,j,k)
-              epsilondev(:,2,j,k,ispec) = epsilondev_loc(:,2,j,k)
-              epsilondev(:,3,j,k,ispec) = epsilondev_loc(:,3,j,k)
-              epsilondev(:,4,j,k,ispec) = epsilondev_loc(:,4,j,k)
-              epsilondev(:,5,j,k,ispec) = epsilondev_loc(:,5,j,k)
-          enddo
-        enddo
-      endif
-
-    endif   ! end test to exclude fictitious elements in central cube
-
-  enddo ! spectral element loop
-
-  end subroutine compute_forces_inner_core_Dev
-

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/noise_tomography.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/noise_tomography.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/noise_tomography.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -239,6 +239,7 @@
   ! output parameters
   ! local parameters
   integer :: reclen,ier
+  integer(kind=8) :: filesize
   character(len=150) :: outputname
 
 
@@ -292,14 +293,22 @@
 
   if (NOISE_TOMOGRAPHY/=0) then
      ! save/read the surface movie using the same c routine as we do for absorbing boundaries (file ID is 9)
-     reclen=CUSTOM_REAL*NDIM*NGLLX*NGLLY*NSPEC_TOP*NSTEP
+     ! size of single record
+     reclen=CUSTOM_REAL*NDIM*NGLLX*NGLLY*NSPEC_TOP
+     ! total file size
+     filesize = reclen
+     filesize = filesize*NSTEP
+     
      write(outputname,"('/proc',i6.6,'_surface_movie')") myrank
      if (NOISE_TOMOGRAPHY==1) call open_file_abs_w(9,trim(LOCAL_PATH)//trim(outputname), &
-                                      len_trim(trim(LOCAL_PATH)//trim(outputname)),reclen)
+                                      len_trim(trim(LOCAL_PATH)//trim(outputname)), &
+                                      filesize)
      if (NOISE_TOMOGRAPHY==2) call open_file_abs_r(9,trim(LOCAL_PATH)//trim(outputname), &
-                                      len_trim(trim(LOCAL_PATH)//trim(outputname)),reclen)
+                                      len_trim(trim(LOCAL_PATH)//trim(outputname)), &
+                                      filesize)
      if (NOISE_TOMOGRAPHY==3) call open_file_abs_r(9,trim(LOCAL_PATH)//trim(outputname), &
-                                      len_trim(trim(LOCAL_PATH)//trim(outputname)),reclen)
+                                      len_trim(trim(LOCAL_PATH)//trim(outputname)), &
+                                      filesize)
   endif
 
   end subroutine check_parameters_noise

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/read_mesh_databases.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/read_mesh_databases.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/read_mesh_databases.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -809,6 +809,7 @@
   integer NSTEP
 
   ! local parameters
+  integer(kind=8) :: filesize  
   character(len=150) prname
 
 
@@ -829,7 +830,14 @@
 
   if (nspec2D_xmin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+    
+    ! size of single record
     reclen_xmin_crust_mantle = CUSTOM_REAL * (NDIM * NGLLY * NGLLZ * nspec2D_xmin_crust_mantle)
+
+    ! total file size
+    filesize = reclen_xmin_crust_mantle
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=51,file=trim(prname)//'absorb_xmin.bin', &
 !            status='old',action='read',form='unformatted',access='direct', &
@@ -840,16 +848,23 @@
 !            recl=reclen_xmin_crust_mantle+2*4)
 
       call open_file_abs_r(0,trim(prname)//'absorb_xmin.bin',len_trim(trim(prname)//'absorb_xmin.bin'), &
-                          reclen_xmin_crust_mantle*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(0,trim(prname)//'absorb_xmin.bin',len_trim(trim(prname)//'absorb_xmin.bin'), &
-                          reclen_xmin_crust_mantle*NSTEP)
+                          filesize)
     endif
   endif
 
   if (nspec2D_xmax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+    
+    ! size of single record
     reclen_xmax_crust_mantle = CUSTOM_REAL * (NDIM * NGLLY * NGLLZ * nspec2D_xmax_crust_mantle)
+    
+    ! total file size
+    filesize = reclen_xmax_crust_mantle
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=52,file=trim(prname)//'absorb_xmax.bin', &
 !            status='old',action='read',form='unformatted',access='direct', &
@@ -860,16 +875,24 @@
 !            recl=reclen_xmax_crust_mantle+2*4)
 
       call open_file_abs_r(1,trim(prname)//'absorb_xmax.bin',len_trim(trim(prname)//'absorb_xmax.bin'), &
-                          reclen_xmax_crust_mantle*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(1,trim(prname)//'absorb_xmax.bin',len_trim(trim(prname)//'absorb_xmax.bin'), &
-                          reclen_xmax_crust_mantle*NSTEP)
+                          filesize)
     endif
   endif
 
   if (nspec2D_ymin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+    
+    ! size of single record
     reclen_ymin_crust_mantle = CUSTOM_REAL * (NDIM * NGLLX * NGLLZ * nspec2D_ymin_crust_mantle)
+
+    ! total file size
+    filesize = reclen_ymin_crust_mantle
+    filesize = filesize*NSTEP
+
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=53,file=trim(prname)//'absorb_ymin.bin', &
 !            status='old',action='read',form='unformatted',access='direct',&
@@ -880,16 +903,23 @@
 !            recl=reclen_ymin_crust_mantle+2*4)
 
       call open_file_abs_r(2,trim(prname)//'absorb_ymin.bin',len_trim(trim(prname)//'absorb_ymin.bin'), &
-                          reclen_ymin_crust_mantle*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(2,trim(prname)//'absorb_ymin.bin',len_trim(trim(prname)//'absorb_ymin.bin'), &
-                          reclen_ymin_crust_mantle*NSTEP)
+                          filesize)
     endif
   endif
 
   if (nspec2D_ymax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+    
+    ! size of single record
     reclen_ymax_crust_mantle = CUSTOM_REAL * (NDIM * NGLLX * NGLLZ * nspec2D_ymax_crust_mantle)
+
+    ! total file size
+    filesize = reclen_ymax_crust_mantle
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=54,file=trim(prname)//'absorb_ymax.bin', &
 !            status='old',action='read',form='unformatted',access='direct',&
@@ -900,10 +930,10 @@
 !            recl=reclen_ymax_crust_mantle+2*4)
 
       call open_file_abs_r(3,trim(prname)//'absorb_ymax.bin',len_trim(trim(prname)//'absorb_ymax.bin'), &
-                          reclen_ymax_crust_mantle*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(3,trim(prname)//'absorb_ymax.bin',len_trim(trim(prname)//'absorb_ymax.bin'), &
-                          reclen_ymax_crust_mantle*NSTEP)
+                          filesize)
     endif
   endif
 
@@ -925,7 +955,14 @@
 
   if (nspec2D_xmin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+    
+    ! size of single record
     reclen_xmin_outer_core = CUSTOM_REAL * (NGLLY * NGLLZ * nspec2D_xmin_outer_core)
+    
+    ! total file size
+    filesize = reclen_xmin_outer_core
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=61,file=trim(prname)//'absorb_xmin.bin', &
 !            status='old',action='read',form='unformatted',access='direct', &
@@ -936,16 +973,23 @@
 !            recl=reclen_xmin_outer_core+2*4)
 
       call open_file_abs_r(4,trim(prname)//'absorb_xmin.bin',len_trim(trim(prname)//'absorb_ymax.bin'), &
-                          reclen_xmin_outer_core*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(4,trim(prname)//'absorb_xmin.bin',len_trim(trim(prname)//'absorb_ymax.bin'), &
-                          reclen_xmin_outer_core*NSTEP)
+                          filesize)
     endif
   endif
 
   if (nspec2D_xmax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+    
+    ! size of single record
     reclen_xmax_outer_core = CUSTOM_REAL * (NGLLY * NGLLZ * nspec2D_xmax_outer_core)
+
+    ! total file size
+    filesize = reclen_xmax_outer_core
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=62,file=trim(prname)//'absorb_xmax.bin', &
 !            status='old',action='read',form='unformatted',access='direct', &
@@ -956,17 +1000,24 @@
 !            recl=reclen_xmax_outer_core+2*4)
 
       call open_file_abs_r(5,trim(prname)//'absorb_xmax.bin',len_trim(trim(prname)//'absorb_xmax.bin'), &
-                          reclen_xmax_outer_core*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(5,trim(prname)//'absorb_xmax.bin',len_trim(trim(prname)//'absorb_xmax.bin'), &
-                          reclen_xmax_outer_core*NSTEP)
+                          filesize)
    endif
 
   endif
 
   if (nspec2D_ymin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+    
+    ! size of single record
     reclen_ymin_outer_core = CUSTOM_REAL * (NGLLX * NGLLZ * nspec2D_ymin_outer_core)
+
+    ! total file size
+    filesize = reclen_ymin_outer_core
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=63,file=trim(prname)//'absorb_ymin.bin', &
 !            status='old',action='read',form='unformatted',access='direct',&
@@ -977,17 +1028,24 @@
 !            recl=reclen_ymin_outer_core+2*4)
 
       call open_file_abs_r(6,trim(prname)//'absorb_ymin.bin',len_trim(trim(prname)//'absorb_ymin.bin'), &
-                          reclen_ymin_outer_core*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(6,trim(prname)//'absorb_ymin.bin',len_trim(trim(prname)//'absorb_ymin.bin'), &
-                          reclen_ymin_outer_core*NSTEP)
+                          filesize)
 
     endif
   endif
 
   if (nspec2D_ymax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
     .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      
+    ! size of single record
     reclen_ymax_outer_core = CUSTOM_REAL * (NGLLX * NGLLZ * nspec2D_ymax_outer_core)
+
+    ! total file size
+    filesize = reclen_ymax_outer_core
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=64,file=trim(prname)//'absorb_ymax.bin', &
 !            status='old',action='read',form='unformatted',access='direct',&
@@ -998,17 +1056,24 @@
 !            recl=reclen_ymax_outer_core+2*4)
 
       call open_file_abs_r(7,trim(prname)//'absorb_ymax.bin',len_trim(trim(prname)//'absorb_ymax.bin'), &
-                          reclen_ymax_outer_core*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(7,trim(prname)//'absorb_ymax.bin',len_trim(trim(prname)//'absorb_ymax.bin'), &
-                          reclen_ymax_outer_core*NSTEP)
+                          filesize)
 
     endif
   endif
 
   if (NSPEC2D_BOTTOM(IREGION_OUTER_CORE) > 0 .and. &
      (SIMULATION_TYPE == 3 .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD)))then
+     
+    ! size of single record
     reclen_zmin = CUSTOM_REAL * (NGLLX * NGLLY * NSPEC2D_BOTTOM(IREGION_OUTER_CORE))
+
+    ! total file size
+    filesize = reclen_zmin
+    filesize = filesize*NSTEP
+    
     if (SIMULATION_TYPE == 3) then
 !      open(unit=65,file=trim(prname)//'absorb_zmin.bin', &
 !            status='old',action='read',form='unformatted',access='direct',&
@@ -1019,10 +1084,10 @@
 !            recl=reclen_zmin+2*4)
 
       call open_file_abs_r(8,trim(prname)//'absorb_zmin.bin',len_trim(trim(prname)//'absorb_zmin.bin'), &
-                          reclen_zmin*NSTEP)
+                          filesize)
     else
       call open_file_abs_w(8,trim(prname)//'absorb_zmin.bin',len_trim(trim(prname)//'absorb_zmin.bin'), &
-                          reclen_zmin*NSTEP)
+                          filesize)
     endif
   endif
 

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/setup_sources_receivers.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/setup_sources_receivers.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/setup_sources_receivers.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -109,7 +109,9 @@
   character(len=3),dimension(NDIM) :: comp
   character(len=256) :: filename,adj_source_file,system_command,filename_new
   character(len=2) :: bic
-
+  ! makes smaller hdur for movies
+  logical,parameter :: USE_SMALLER_HDUR_MOVIE = .false.
+  
 ! sources
   ! BS BS moved open statement and writing of first lines into sr.vtk before the
   ! call to locate_sources, where further write statements to that file follow
@@ -139,13 +141,21 @@
   if(abs(minval(tshift_cmt)) > TINYVAL) call exit_MPI(myrank,'one tshift_cmt must be zero, others must be positive')
 
   ! filter source time function by Gaussian with hdur = HDUR_MOVIE when outputing movies or shakemaps
-  if (MOVIE_SURFACE .or. MOVIE_VOLUME ) then
-     hdur = sqrt(hdur**2 + HDUR_MOVIE**2)
-     if(myrank == 0) then
-        write(IMAIN,*)
-        write(IMAIN,*) 'Each source is being convolved with HDUR_MOVIE = ',HDUR_MOVIE
-        write(IMAIN,*)
-     endif
+  if (MOVIE_SURFACE .or. MOVIE_VOLUME ) then     
+    ! smaller hdur_movie will do
+    if( USE_SMALLER_HDUR_MOVIE ) then
+      ! hdur_movie gets assigned an automatic value based on the simulation resolution
+      ! this will make that a bit smaller to have a higher-frequency movie output
+      HDUR_MOVIE = 0.5* HDUR_MOVIE
+    endif
+    
+    ! new hdur for simulation
+    hdur = sqrt(hdur**2 + HDUR_MOVIE**2)
+    if(myrank == 0) then
+      write(IMAIN,*)
+      write(IMAIN,*) 'Each source is being convolved with HDUR_MOVIE = ',HDUR_MOVIE
+      write(IMAIN,*)
+    endif
   endif
 
   ! convert the half duration for triangle STF to the one for gaussian STF

Copied: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.F90 (from rev 18970, seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.f90)
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.F90	                        (rev 0)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.F90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -0,0 +1,4507 @@
+!=====================================================================
+!
+!          S p e c f e m 3 D  G l o b e  V e r s i o n  5 . 1
+!          --------------------------------------------------
+!
+!          Main authors: Dimitri Komatitsch and Jeroen Tromp
+!                        Princeton University, USA
+!             and University of Pau / CNRS / INRIA, France
+! (c) Princeton University / California Institute of Technology and University of Pau / CNRS / INRIA
+!                            April 2011
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or
+! (at your option) any later version.
+!
+! This program is distributed in the hope that it will be useful,
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+! GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along
+! with this program; if not, write to the Free Software Foundation, Inc.,
+! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+!
+!=====================================================================
+!
+! United States and French Government Sponsorship Acknowledged.
+
+! preprocessing definition: #define _HANDOPT :  turns hand-optimized code on
+!                                         #undef _HANDOPT :  turns hand-optimized code off
+! or compile with: -D_HANDOPT
+!#define _HANDOPT
+ 
+! note: these hand optimizations should help compilers to pipeline the code and make better use of the cache;
+!          depending on compilers, it can further decrease the computation time by ~ 30%.
+!          the original routines are commented with "! way 1", the hand-optimized routines with  "! way 2"
+
+  program xspecfem3D
+
+  implicit none
+
+! standard include of the MPI library
+  include 'mpif.h'
+
+  include "constants.h"
+  include "precision.h"
+
+! include values created by the mesher
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+!=======================================================================!
+!                                                                       !
+!   specfem3D is a 3-D spectral-element solver for the Earth.           !
+!   It uses a mesh generated by program meshfem3D                       !
+!                                                                       !
+!=======================================================================!
+!
+! If you use this code for your own research, please cite at least one article
+! written by the developers of the package, for instance:
+!
+! @ARTICLE{TrKoLi08,
+! author = {Jeroen Tromp and Dimitri Komatitsch and Qinya Liu},
+! title = {Spectral-Element and Adjoint Methods in Seismology},
+! journal = {Communications in Computational Physics},
+! year = {2008},
+! volume = {3},
+! pages = {1-32},
+! number = {1}}
+!
+! or
+!
+! @ARTICLE{VaCaSaKoVi99,
+! author = {R. Vai and J. M. Castillo-Covarrubias and F. J. S\'anchez-Sesma and
+! D. Komatitsch and J. P. Vilotte},
+! title = {Elastic wave propagation in an irregularly layered medium},
+! journal = {Soil Dynamics and Earthquake Engineering},
+! year = {1999},
+! volume = {18},
+! pages = {11-18},
+! number = {1},
+! doi = {10.1016/S0267-7261(98)00027-X}}
+!
+! @ARTICLE{LeChKoHuTr09,
+! author = {Shiann Jong Lee and Yu Chang Chan and Dimitri Komatitsch and Bor
+! Shouh Huang and Jeroen Tromp},
+! title = {Effects of realistic surface topography on seismic ground motion
+! in the {Y}angminshan region of {T}aiwan based upon the spectral-element
+! method and {LiDAR DTM}},
+! journal = {Bull. Seismol. Soc. Am.},
+! year = {2009},
+! volume = {99},
+! pages = {681-693},
+! number = {2A},
+! doi = {10.1785/0120080264}}
+!
+! @ARTICLE{LeChLiKoHuTr08,
+! author = {Shiann Jong Lee and How Wei Chen and Qinya Liu and Dimitri Komatitsch
+! and Bor Shouh Huang and Jeroen Tromp},
+! title = {Three-Dimensional Simulations of Seismic Wave Propagation in the
+! {T}aipei Basin with Realistic Topography Based upon the Spectral-Element Method},
+! journal = {Bull. Seismol. Soc. Am.},
+! year = {2008},
+! volume = {98},
+! pages = {253-264},
+! number = {1},
+! doi = {10.1785/0120070033}}
+!
+! @ARTICLE{LeKoHuTr09,
+! author = {S. J. Lee and Dimitri Komatitsch and B. S. Huang and J. Tromp},
+! title = {Effects of topography on seismic wave propagation: An example from
+! northern {T}aiwan},
+! journal = {Bull. Seismol. Soc. Am.},
+! year = {2009},
+! volume = {99},
+! pages = {314-325},
+! number = {1},
+! doi = {10.1785/0120080020}}
+!
+! @ARTICLE{KoErGoMi10,
+! author = {Dimitri Komatitsch and Gordon Erlebacher and Dominik G\"oddeke and
+! David Mich\'ea},
+! title = {High-order finite-element seismic wave propagation modeling with
+! {MPI} on a large {GPU} cluster},
+! journal = {J. Comput. Phys.},
+! year = {2010},
+! volume = {229},
+! pages = {7692-7714},
+! number = {20},
+! doi = {10.1016/j.jcp.2010.06.024}}
+!
+! @ARTICLE{KoGoErMi10,
+! author = {Dimitri Komatitsch and Dominik G\"oddeke and Gordon Erlebacher and
+! David Mich\'ea},
+! title = {Modeling the propagation of elastic waves using spectral elements
+! on a cluster of 192 {GPU}s},
+! journal = {Computer Science Research and Development},
+! year = {2010},
+! volume = {25},
+! pages = {75-82},
+! number = {1-2},
+! doi = {10.1007/s00450-010-0109-1}}
+!
+! @ARTICLE{KoMiEr09,
+! author = {Dimitri Komatitsch and David Mich\'ea and Gordon Erlebacher},
+! title = {Porting a high-order finite-element earthquake modeling application
+! to {NVIDIA} graphics cards using {CUDA}},
+! journal = {Journal of Parallel and Distributed Computing},
+! year = {2009},
+! volume = {69},
+! pages = {451-460},
+! number = {5},
+! doi = {10.1016/j.jpdc.2009.01.006}}
+!
+! @INCOLLECTION{ChKoViCaVaFe07,
+! author = {Emmanuel Chaljub and Dimitri Komatitsch and Jean-Pierre Vilotte and
+! Yann Capdeville and Bernard Valette and Gaetano Festa},
+! title = {Spectral Element Analysis in Seismology},
+! booktitle = {Advances in Wave Propagation in Heterogeneous Media},
+! publisher = {Elsevier - Academic Press},
+! year = {2007},
+! editor = {Ru-Shan Wu and Val\'erie Maupin},
+! volume = {48},
+! series = {Advances in Geophysics},
+! pages = {365-419}}
+!
+! @ARTICLE{KoVi98,
+! author={D. Komatitsch and J. P. Vilotte},
+! title={The spectral-element method: an efficient tool to simulate the seismic response of 2{D} and 3{D} geological structures},
+! journal={Bull. Seismol. Soc. Am.},
+! year=1998,
+! volume=88,
+! number=2,
+! pages={368-392}}
+!
+! @ARTICLE{KoTr99,
+! author={D. Komatitsch and J. Tromp},
+! year=1999,
+! title={Introduction to the spectral-element method for 3-{D} seismic wave propagation},
+! journal={Geophys. J. Int.},
+! volume=139,
+! number=3,
+! pages={806-822},
+! doi={10.1046/j.1365-246x.1999.00967.x}}
+!
+! @ARTICLE{KoRiTr02,
+! author={D. Komatitsch and J. Ritsema and J. Tromp},
+! year=2002,
+! title={The Spectral-Element Method, {B}eowulf Computing, and Global Seismology},
+! journal={Science},
+! volume=298,
+! number=5599,
+! pages={1737-1742},
+! doi={10.1126/science.1076024}}
+!
+! @ARTICLE{KoTr02a,
+! author={D. Komatitsch and J. Tromp},
+! year=2002,
+! title={Spectral-Element Simulations of Global Seismic Wave Propagation{-I. V}alidation},
+! journal={Geophys. J. Int.},
+! volume=149,
+! number=2,
+! pages={390-412},
+! doi={10.1046/j.1365-246X.2002.01653.x}}
+!
+! @ARTICLE{KoTr02b,
+! author={D. Komatitsch and J. Tromp},
+! year=2002,
+! title={Spectral-Element Simulations of Global Seismic Wave Propagation{-II. 3-D} Models, Oceans, Rotation, and Self-Gravitation},
+! journal={Geophys. J. Int.},
+! volume=150,
+! pages={303-318},
+! number=1,
+! doi={10.1046/j.1365-246X.2002.01716.x}}
+!
+! and/or another article from http://web.univ-pau.fr/~dkomati1/publications.html
+!
+!
+! If you use the kernel capabilities of the code, please cite at least one article
+! written by the developers of the package, for instance:
+!
+! @ARTICLE{TrKoLi08,
+! author = {Jeroen Tromp and Dimitri Komatitsch and Qinya Liu},
+! title = {Spectral-Element and Adjoint Methods in Seismology},
+! journal = {Communications in Computational Physics},
+! year = {2008},
+! volume = {3},
+! pages = {1-32},
+! number = {1}}
+!
+! or
+!
+! @ARTICLE{LiTr06,
+! author={Qinya Liu and Jeroen Tromp},
+! title={Finite-frequency kernels based on adjoint methods},
+! journal={Bull. Seismol. Soc. Am.},
+! year=2006,
+! volume=96,
+! number=6,
+! pages={2383-2397},
+! doi={10.1785/0120060041}}
+!
+! If you use 3-D model S20RTS, please cite:
+!
+! @ARTICLE{RiVa00,
+! author={J. Ritsema and H. J. {Van Heijst}},
+! year=2000,
+! title={Seismic imaging of structural heterogeneity in {E}arth's mantle: Evidence for large-scale mantle flow},
+! journal={Science Progress},
+! volume=83,
+! pages={243-259}}
+!
+! Reference frame - convention:
+! ----------------------------
+!
+! The code uses the following convention for the reference frame:
+!
+!  - X axis is East
+!  - Y axis is North
+!  - Z axis is up
+!
+! Note that this convention is different from both the Aki-Richards convention
+! and the Harvard CMT convention.
+!
+! Let us recall that the Aki-Richards convention is:
+!
+!  - X axis is North
+!  - Y axis is East
+!  - Z axis is down
+!
+! and that the Harvard CMT convention is:
+!
+!  - X axis is South
+!  - Y axis is East
+!  - Z axis is up
+!
+! To report bugs or suggest improvements to the code, please send an email
+! to Jeroen Tromp <jtromp AT princeton.edu> and/or use our online
+! bug tracking system at http://www.geodynamics.org/roundup .
+!
+! Evolution of the code:
+! ---------------------
+!
+! v. 5.1, Dimitri Komatitsch, University of Toulouse, France and Ebru Bozdag, Princeton University, USA, February 2011:
+!     non blocking MPI for much better scaling on large clusters;
+!     new convention for the name of seismograms, to conform to the IRIS standard;
+!     new directory structure
+!
+! v. 5.0 aka Tiger, many developers some with Princeton Tiger logo on their shirts, February 2010:
+!     new moho mesh stretching honoring crust2.0 moho depths,
+!     new attenuation assignment, new SAC headers, new general crustal models,
+!     faster performance due to Deville routines and enhanced loop unrolling,
+!     slight changes in code structure (see also trivia at program start)
+!
+! v. 4.0 David Michea and Dimitri Komatitsch, University of Pau, France, February 2008:
+!      new doubling brick in the mesh, new perfectly load-balanced mesh,
+!      more flexible routines for mesh design, new inflated central cube
+!      with optimized shape, far fewer mesh files saved by the mesher,
+!      global arrays sorted to speed up the simulation, seismos can be
+!      written by the master, one more doubling level at the bottom
+!      of the outer core if needed (off by default)
+!
+! v. 3.6 Many people, many affiliations, September 2006:
+!      adjoint and kernel calculations, fixed IASP91 model,
+!      added AK135 and 1066a, fixed topography/bathymetry routine,
+!      new attenuation routines, faster and better I/Os on very large
+!      systems, many small improvements and bug fixes, new "configure"
+!      script, new Pyre version, new user's manual etc.
+!
+! v. 3.5 Dimitri Komatitsch, Brian Savage and Jeroen Tromp, Caltech, July 2004:
+!      any size of chunk, 3D attenuation, case of two chunks,
+!      more precise topography/bathymetry model, new Par_file structure
+!
+! v. 3.4 Dimitri Komatitsch and Jeroen Tromp, Caltech, August 2003:
+!      merged global and regional codes, no iterations in fluid, better movies
+!
+! v. 3.3 Dimitri Komatitsch, Caltech, September 2002:
+!      flexible mesh doubling in outer core, inlined code, OpenDX support
+!
+! v. 3.2 Jeroen Tromp, Caltech, July 2002:
+!      multiple sources and flexible PREM reading
+!
+! v. 3.1 Dimitri Komatitsch, Caltech, June 2002:
+!      vectorized loops in solver and merged central cube
+!
+! v. 3.0 Dimitri Komatitsch and Jeroen Tromp, Caltech, May 2002:
+!   ported to SGI and Compaq, double precision solver, more general anisotropy
+!
+! v. 2.3 Dimitri Komatitsch and Jeroen Tromp, Caltech, August 2001:
+!                       gravity, rotation, oceans and 3-D models
+!
+! v. 2.2 Dimitri Komatitsch and Jeroen Tromp, Caltech, USA, March 2001:
+!                       final MPI package
+!
+! v. 2.0 Dimitri Komatitsch, Harvard, USA, January 2000: MPI code for the globe
+!
+! v. 1.0 Dimitri Komatitsch, UNAM, Mexico, June 1999: first MPI code for a chunk
+!
+! Jeroen Tromp and Dimitri Komatitsch, Harvard, USA, July 1998: first chunk solver using OpenMP on a Sun machine
+!
+! Dimitri Komatitsch, IPG Paris, France, December 1996: first 3-D solver for the CM-5 Connection Machine,
+!    parallelized on 128 processors using Connection Machine Fortran
+!
+! From Dahlen and Tromp (1998):
+! ----------------------------
+!
+! Gravity is approximated by solving eq (3.259) without the Phi_E' term
+! The ellipsoidal reference model is that of section 14.1
+! The transversely isotropic expression for PREM is that of eq (8.190)
+!
+! Formulation in the fluid (acoustic) outer core:
+! -----------------------------------------------
+!
+! In case of an acoustic medium, a displacement potential Chi is used
+! as in Chaljub and Valette, Geophysical Journal International, vol. 158,
+! p. 131-141 (2004) and *NOT* a velocity potential as in Komatitsch and Tromp,
+! Geophysical Journal International, vol. 150, p. 303-318 (2002).
+! This permits acoustic-elastic coupling based on a non-iterative time scheme.
+! Displacement if we ignore gravity is then: u = grad(Chi)
+! (In the context of the Cowling approximation displacement is
+! u = grad(rho * Chi) / rho, *not* u = grad(Chi).)
+! Velocity is then: v = grad(Chi_dot)       (Chi_dot being the time derivative of Chi)
+! and pressure is: p = - rho * Chi_dot_dot  (Chi_dot_dot being the time second derivative of Chi).
+! The source in an acoustic element is a pressure source.
+! The potential in the outer core is called displ_outer_core for simplicity.
+! Its first time derivative is called veloc_outer_core.
+! Its second time derivative is called accel_outer_core.
+
+! memory variables and standard linear solids for attenuation
+  real(kind=CUSTOM_REAL), dimension(ATT1,ATT2,ATT3,ATT4) :: one_minus_sum_beta_crust_mantle, factor_scale_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(ATT1,ATT2,ATT3,ATT5) :: one_minus_sum_beta_inner_core, factor_scale_inner_core
+
+  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval, betaval, gammaval
+  real(kind=CUSTOM_REAL), dimension(N_SLS,ATT1,ATT2,ATT3,ATT4) :: factor_common_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(N_SLS,ATT1,ATT2,ATT3,ATT5) :: factor_common_inner_core
+
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_OR_ATT) :: epsilondev_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STRAIN_ONLY) :: eps_trace_over_3_crust_mantle
+
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ATTENUATION) :: R_memory_inner_core
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STR_OR_ATT) :: epsilondev_inner_core
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STRAIN_ONLY) :: eps_trace_over_3_inner_core
+
+! ADJOINT
+  real(kind=CUSTOM_REAL), dimension(N_SLS) :: b_alphaval, b_betaval, b_gammaval
+
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_AND_ATT) :: b_R_memory_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: b_epsilondev_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: b_eps_trace_over_3_crust_mantle
+
+  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STR_AND_ATT) :: b_R_memory_inner_core
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ADJOINT) :: b_epsilondev_inner_core
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ADJOINT) :: b_eps_trace_over_3_inner_core
+
+! for matching with central cube in inner core
+  integer, dimension(:), allocatable :: sender_from_slices_to_cube
+  integer, dimension(:,:), allocatable :: ibool_central_cube
+  double precision, dimension(:,:), allocatable :: buffer_slices,b_buffer_slices,buffer_slices2
+  double precision, dimension(:,:,:), allocatable :: buffer_all_cube_from_slices,b_buffer_all_cube_from_slices
+  integer nb_msgs_theor_in_cube,non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices,receiver_cube_from_slices
+
+  integer nspec2D_xmin_inner_core,nspec2D_xmax_inner_core,nspec2D_ymin_inner_core,nspec2D_ymax_inner_core
+
+! to save movie frames
+  integer nmovie_points,NIT
+  real(kind=CUSTOM_REAL), dimension(:), allocatable :: &
+      store_val_x,store_val_y,store_val_z, &
+      store_val_ux,store_val_uy,store_val_uz
+  real(kind=CUSTOM_REAL), dimension(:,:), allocatable :: &
+      store_val_x_all,store_val_y_all,store_val_z_all, &
+      store_val_ux_all,store_val_uy_all,store_val_uz_all
+
+! to save movie volume
+  integer :: npoints_3dmovie,nspecel_3dmovie
+  integer, dimension(NGLOB_CRUST_MANTLE) :: num_ibool_3dmovie
+  double precision :: scalingval
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_OR_ATT) :: muvstore_crust_mantle_3dmovie
+  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: nu_3dmovie
+  logical, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STRAIN_ONLY) :: mask_3dmovie
+
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_OR_ATT) :: Iepsilondev_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STRAIN_ONLY) :: Ieps_trace_over_3_crust_mantle
+
+! use integer array to store values
+  integer, dimension(NX_BATHY,NY_BATHY) :: ibathy_topo
+
+! for crust/oceans coupling
+  integer, dimension(NSPEC2DMAX_XMIN_XMAX_CM) :: ibelm_xmin_crust_mantle,ibelm_xmax_crust_mantle
+  integer, dimension(NSPEC2DMAX_YMIN_YMAX_CM) :: ibelm_ymin_crust_mantle,ibelm_ymax_crust_mantle
+  integer, dimension(NSPEC2D_BOTTOM_CM) :: ibelm_bottom_crust_mantle
+  integer, dimension(NSPEC2D_TOP_CM) :: ibelm_top_crust_mantle
+
+! additional mass matrix for ocean load
+  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE_OCEANS) :: rmass_ocean_load
+
+! flag to mask ocean-bottom degrees of freedom for ocean load
+  logical, dimension(NGLOB_CRUST_MANTLE_OCEANS) :: updated_dof_ocean_load
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_BOTTOM_CM) :: jacobian2D_bottom_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_TOP_CM) :: jacobian2D_top_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_CM) :: jacobian2D_xmin_crust_mantle,&
+  jacobian2D_xmax_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ,NSPEC2DMAX_YMIN_YMAX_CM) :: jacobian2D_ymin_crust_mantle,&
+  jacobian2D_ymax_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_CM) :: &
+  normal_xmin_crust_mantle,normal_xmax_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2DMAX_YMIN_YMAX_CM) :: &
+  normal_ymin_crust_mantle,normal_ymax_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_BOTTOM_CM) :: normal_bottom_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_TOP_CM) :: normal_top_crust_mantle
+
+! Stacey
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STACEY) :: rho_vp_crust_mantle,rho_vs_crust_mantle
+  integer nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle,nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle
+  integer, dimension(2,NSPEC2DMAX_YMIN_YMAX_CM) :: nimin_crust_mantle,nimax_crust_mantle,nkmin_eta_crust_mantle
+  integer, dimension(2,NSPEC2DMAX_XMIN_XMAX_CM) :: njmin_crust_mantle,njmax_crust_mantle,nkmin_xi_crust_mantle
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_STACEY) :: vp_outer_core
+  integer nspec2D_xmin_outer_core,nspec2D_xmax_outer_core,nspec2D_ymin_outer_core,nspec2D_ymax_outer_core
+  integer, dimension(2,NSPEC2DMAX_YMIN_YMAX_OC) :: nimin_outer_core,nimax_outer_core,nkmin_eta_outer_core
+  integer, dimension(2,NSPEC2DMAX_XMIN_XMAX_OC) :: njmin_outer_core,njmax_outer_core,nkmin_xi_outer_core
+
+! arrays to couple with the fluid regions by pointwise matching
+  integer, dimension(NSPEC2DMAX_XMIN_XMAX_OC) :: ibelm_xmin_outer_core,ibelm_xmax_outer_core
+  integer, dimension(NSPEC2DMAX_YMIN_YMAX_OC) :: ibelm_ymin_outer_core,ibelm_ymax_outer_core
+  integer, dimension(NSPEC2D_BOTTOM_OC) :: ibelm_bottom_outer_core
+  integer, dimension(NSPEC2D_TOP_OC) :: ibelm_top_outer_core
+
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_OC) :: normal_xmin_outer_core,normal_xmax_outer_core
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLZ,NSPEC2DMAX_YMIN_YMAX_OC) :: normal_ymin_outer_core,normal_ymax_outer_core
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_BOTTOM_OC) :: normal_bottom_outer_core
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_TOP_OC) :: normal_top_outer_core
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_BOTTOM_OC) :: jacobian2D_bottom_outer_core
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_TOP_OC) :: jacobian2D_top_outer_core
+  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_OC) :: jacobian2D_xmin_outer_core,jacobian2D_xmax_outer_core
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ,NSPEC2DMAX_YMIN_YMAX_OC) :: jacobian2D_ymin_outer_core,jacobian2D_ymax_outer_core
+
+
+  integer, dimension(NSPEC2DMAX_XMIN_XMAX_IC) :: ibelm_xmin_inner_core,ibelm_xmax_inner_core
+  integer, dimension(NSPEC2DMAX_YMIN_YMAX_IC) :: ibelm_ymin_inner_core,ibelm_ymax_inner_core
+  integer, dimension(NSPEC2D_BOTTOM_IC) :: ibelm_bottom_inner_core
+  integer, dimension(NSPEC2D_TOP_IC) :: ibelm_top_inner_core
+
+! for ellipticity
+  integer nspl
+  double precision rspl(NR),espl(NR),espl2(NR)
+
+! for conversion from x y z to r theta phi
+  real(kind=CUSTOM_REAL) rval,thetaval,phival
+
+! ---- arrays to assemble between chunks
+
+! communication pattern for faces between chunks
+  integer, dimension(NUMMSGS_FACES_VAL) :: iprocfrom_faces,iprocto_faces,imsg_type
+
+! communication pattern for corners between chunks
+  integer, dimension(NCORNERSCHUNKS_VAL) :: iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners
+
+! indirect addressing for each message for faces and corners of the chunks
+! a given slice can belong to at most one corner and at most two faces
+  integer NGLOB2DMAX_XY
+  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_crust_mantle, &
+      iboolfaces_outer_core,iboolfaces_inner_core
+
+! this for non blocking MPI
+
+! buffers for send and receive between faces of the slices and the chunks
+! we use the same buffers to assemble scalars and vectors because vectors are
+! always three times bigger and therefore scalars can use the first part
+! of the vector buffer in memory even if it has an additional index here
+  integer :: npoin2D_max_all_CM_IC
+  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: buffer_send_faces,buffer_received_faces, &
+                                                           b_buffer_send_faces,b_buffer_received_faces
+
+! for non blocking communications
+  logical, dimension(NSPEC_CRUST_MANTLE) :: is_on_a_slice_edge_crust_mantle
+  logical, dimension(NSPEC_OUTER_CORE) :: is_on_a_slice_edge_outer_core
+  logical, dimension(NSPEC_INNER_CORE) :: is_on_a_slice_edge_inner_core
+  logical, dimension(NGLOB_CRUST_MANTLE) :: mask_ibool
+  real :: percentage_edge
+
+! assembling phase number for non blocking MPI
+! iphase is for the crust_mantle, outer_core and inner_core regions
+! iphase_CC is for the central cube
+  integer :: iphase,iphase_CC,icall
+  integer :: b_iphase,b_iphase_CC,b_icall
+
+! -------- arrays specific to each region here -----------
+
+! ----------------- crust, mantle and oceans ---------------------
+
+! mesh parameters
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool_crust_mantle
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: &
+        xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle,&
+        etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+        gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: &
+        xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle
+
+! arrays for isotropic elements stored only where needed to save space
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ISO_MANTLE) :: &
+        rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle
+
+! arrays for anisotropic elements stored only where needed to save space
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_TISO_MANTLE) :: &
+        kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle
+
+! arrays for full anisotropy only when needed
+  integer nspec_iso,nspec_tiso,nspec_ani
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_MANTLE) :: &
+        c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+        c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+        c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+        c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+        c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+        c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+        c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle
+
+! local to global mapping
+!  integer, dimension(NSPEC_CRUST_MANTLE) :: idoubling_crust_mantle
+  logical, dimension(NSPEC_CRUST_MANTLE) :: ispec_is_tiso_crust_mantle
+
+! mass matrix
+  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: rmass_crust_mantle
+
+! displacement, velocity, acceleration
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: &
+     displ_crust_mantle,veloc_crust_mantle,accel_crust_mantle
+
+! ----------------- outer core ---------------------
+
+! mesh parameters
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: ibool_outer_core
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: &
+        xix_outer_core,xiy_outer_core,xiz_outer_core,&
+        etax_outer_core,etay_outer_core,etaz_outer_core, &
+        gammax_outer_core,gammay_outer_core,gammaz_outer_core
+  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: &
+        xstore_outer_core,ystore_outer_core,zstore_outer_core
+
+ real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: &
+        rhostore_outer_core,kappavstore_outer_core
+
+! local to global mapping
+  integer, dimension(NSPEC_OUTER_CORE) :: idoubling_outer_core
+  logical, dimension(NSPEC_OUTER_CORE) :: ispec_is_tiso_outer_core ! only needed for compute_boundary_kernel()
+
+! mass matrix
+  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: rmass_outer_core
+
+! velocity potential
+  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: displ_outer_core, &
+    veloc_outer_core,accel_outer_core
+
+! ----------------- inner core ---------------------
+
+! mesh parameters
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool_inner_core
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: &
+        xix_inner_core,xiy_inner_core,xiz_inner_core,&
+        etax_inner_core,etay_inner_core,etaz_inner_core, &
+        gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+        rhostore_inner_core, kappavstore_inner_core,muvstore_inner_core
+  real(kind=CUSTOM_REAL), dimension(NGLOB_INNER_CORE) :: &
+        xstore_inner_core,ystore_inner_core,zstore_inner_core
+
+! arrays for inner-core anisotropy only when needed
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_IC) :: &
+        c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+        c13store_inner_core,c44store_inner_core
+
+! local to global mapping
+  integer, dimension(NSPEC_INNER_CORE) :: idoubling_inner_core
+  logical, dimension(NSPEC_INNER_CORE) :: ispec_is_tiso_inner_core ! only needed for computer_boundary_kernel() routine
+
+! mass matrix
+  real(kind=CUSTOM_REAL), dimension(NGLOB_INNER_CORE) :: rmass_inner_core
+
+! displacement, velocity, acceleration
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: &
+     displ_inner_core,veloc_inner_core,accel_inner_core
+
+! Newmark time scheme parameters and non-dimensionalization
+  real(kind=CUSTOM_REAL) time,deltat,deltatover2,deltatsqover2
+  double precision scale_t,scale_t_inv,scale_displ,scale_veloc
+
+! ADJOINT
+  real(kind=CUSTOM_REAL) b_deltat,b_deltatover2,b_deltatsqover2
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE_ADJOINT) :: &
+    b_displ_crust_mantle,b_veloc_crust_mantle,b_accel_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE_ADJOINT) :: &
+    b_displ_outer_core,b_veloc_outer_core,b_accel_outer_core
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE_ADJOINT) :: &
+    b_displ_inner_core,b_veloc_inner_core,b_accel_inner_core
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: div_displ_outer_core
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: b_div_displ_outer_core
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: rho_kl_crust_mantle, &
+     beta_kl_crust_mantle, alpha_kl_crust_mantle, Sigma_kl_crust_mantle
+! For anisotropic kernels (see compute_kernels.f90 for a definition of the array)
+  real(kind=CUSTOM_REAL), dimension(21,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: cijkl_kl_crust_mantle
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: rho_kl_outer_core, &
+     alpha_kl_outer_core
+
+  ! approximate hessian
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:),allocatable :: hess_kl_crust_mantle
+
+  ! check for deviatoric kernel for outer core region
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:),allocatable :: beta_kl_outer_core
+  integer :: nspec_beta_kl_outer_core
+  logical,parameter:: deviatoric_outercore = .false.
+
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ADJOINT) :: rho_kl_inner_core, &
+     beta_kl_inner_core, alpha_kl_inner_core
+
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:), allocatable :: absorb_xmin_crust_mantle5, &
+     absorb_xmax_crust_mantle5, absorb_ymin_crust_mantle5, absorb_ymax_crust_mantle5
+
+  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: absorb_xmin_outer_core, &
+     absorb_xmax_outer_core, absorb_ymin_outer_core, absorb_ymax_outer_core, &
+     absorb_zmin_outer_core
+  integer nabs_xmin_cm,nabs_xmax_cm,nabs_ymin_cm,nabs_ymax_cm
+  integer nabs_xmin_oc,nabs_xmax_oc,nabs_ymin_oc,nabs_ymax_oc,nabs_zmin_oc
+
+  integer reclen_xmin_crust_mantle, reclen_xmax_crust_mantle, reclen_ymin_crust_mantle, &
+     reclen_ymax_crust_mantle, reclen_xmin_outer_core, reclen_xmax_outer_core,&
+     reclen_ymin_outer_core, reclen_ymax_outer_core, reclen_zmin
+
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_OUTER_CORE) :: vector_accel_outer_core,&
+             vector_displ_outer_core, b_vector_displ_outer_core
+
+  integer npoin2D_faces_crust_mantle(NUMFACES_SHARED)
+  integer npoin2D_faces_outer_core(NUMFACES_SHARED)
+  integer npoin2D_faces_inner_core(NUMFACES_SHARED)
+
+! parameters for the source
+  integer it
+  integer, dimension(:), allocatable :: islice_selected_source,ispec_selected_source
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:), allocatable :: sourcearrays
+  double precision, dimension(:,:,:) ,allocatable:: nu_source
+  double precision sec
+  double precision, dimension(:), allocatable :: Mxx,Myy,Mzz,Mxy,Mxz,Myz
+  double precision, dimension(:), allocatable :: xi_source,eta_source,gamma_source
+  double precision, dimension(:), allocatable :: tshift_cmt,hdur,hdur_gaussian
+  double precision, dimension(:), allocatable :: theta_source,phi_source
+  double precision, external :: comp_source_time_function
+  double precision t0
+
+! receiver information
+  integer nrec,nrec_local
+  integer, dimension(:), allocatable :: islice_selected_rec,ispec_selected_rec,number_receiver_global
+  double precision, dimension(:), allocatable :: xi_receiver,eta_receiver,gamma_receiver
+  character(len=150) :: STATIONS,rec_filename
+  double precision, dimension(:,:,:), allocatable :: nu
+  double precision, allocatable, dimension(:) :: stlat,stlon,stele,stbur
+  character(len=MAX_LENGTH_STATION_NAME), dimension(:), allocatable  :: station_name
+  character(len=MAX_LENGTH_NETWORK_NAME), dimension(:), allocatable :: network_name
+
+!ADJOINT
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:,:), allocatable :: adj_sourcearrays
+  integer nrec_simulation, nadj_rec_local
+  integer NSTEP_SUB_ADJ  ! to read input in chunks
+  integer, dimension(:,:), allocatable :: iadjsrc ! to read input in chunks
+  integer, dimension(:), allocatable :: iadjsrc_len,iadj_vec
+! source frechet derivatives
+  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: moment_der
+  real(kind=CUSTOM_REAL), dimension(:,:), allocatable :: sloc_der
+  real(kind=CUSTOM_REAL), dimension(:), allocatable :: stshift_der, shdur_der
+  double precision, dimension(:,:), allocatable :: hpxir_store,hpetar_store,hpgammar_store
+  integer :: nadj_hprec_local
+
+! seismograms
+  integer it_begin,it_end,nit_written
+  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: seismograms
+  integer :: seismo_offset, seismo_current
+
+! non-dimensionalized rotation rate of the Earth times two
+  real(kind=CUSTOM_REAL) two_omega_earth
+
+! for the Euler scheme for rotation
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ROTATION) :: &
+    A_array_rotation,B_array_rotation
+
+! number of faces between chunks
+  integer NUMMSGS_FACES
+
+! number of corners between chunks
+  integer NCORNERSCHUNKS
+
+! number of message types
+  integer NUM_MSG_TYPES
+
+! indirect addressing for each corner of the chunks
+  integer, dimension(NGLOB1D_RADIAL_CM,NUMCORNERS_SHARED) :: iboolcorner_crust_mantle
+  integer, dimension(NGLOB1D_RADIAL_OC,NUMCORNERS_SHARED) :: iboolcorner_outer_core
+  integer, dimension(NGLOB1D_RADIAL_IC,NUMCORNERS_SHARED) :: iboolcorner_inner_core
+
+! buffers for send and receive between corners of the chunks
+  real(kind=CUSTOM_REAL), dimension(NGLOB1D_RADIAL_CM) :: buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
+                                                          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar
+! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB1D_RADIAL_CM + NGLOB1D_RADIAL_IC) :: &
+     buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
+     b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector
+
+! Gauss-Lobatto-Legendre points of integration and weights
+  double precision, dimension(NGLLX) :: xigll,wxgll
+  double precision, dimension(NGLLY) :: yigll,wygll
+  double precision, dimension(NGLLZ) :: zigll,wzgll
+
+! product of weights for gravity term
+  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
+
+! array with derivatives of Lagrange polynomials and precalculated products
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xx,hprimewgll_xx
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xxT,hprimewgll_xxT
+  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLY) :: hprime_yy,hprimewgll_yy
+  real(kind=CUSTOM_REAL), dimension(NGLLZ,NGLLZ) :: hprime_zz,hprimewgll_zz
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY) :: wgllwgll_xy
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ) :: wgllwgll_xz
+  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ) :: wgllwgll_yz
+
+! Lagrange interpolators at receivers
+  double precision, dimension(:,:), allocatable :: hxir_store,hetar_store,hgammar_store
+
+! 2-D addressing and buffers for summation between slices
+  integer, dimension(NGLOB2DMAX_XMIN_XMAX_CM) :: iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle
+  integer, dimension(NGLOB2DMAX_YMIN_YMAX_CM) :: iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle
+
+  integer, dimension(NGLOB2DMAX_XMIN_XMAX_OC) :: iboolleft_xi_outer_core,iboolright_xi_outer_core
+  integer, dimension(NGLOB2DMAX_YMIN_YMAX_OC) :: iboolleft_eta_outer_core,iboolright_eta_outer_core
+
+  integer, dimension(NGLOB2DMAX_XMIN_XMAX_IC) :: iboolleft_xi_inner_core,iboolright_xi_inner_core
+  integer, dimension(NGLOB2DMAX_YMIN_YMAX_IC) :: iboolleft_eta_inner_core,iboolright_eta_inner_core
+
+! for addressing of the slices
+  integer, dimension(NCHUNKS_VAL,0:NPROC_XI_VAL-1,0:NPROC_ETA_VAL-1) :: addressing
+  integer, dimension(0:NPROCTOT_VAL-1) :: ichunk_slice,iproc_xi_slice,iproc_eta_slice
+
+! proc numbers for MPI
+  integer myrank
+
+  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle
+  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_outer_core,npoin2D_eta_outer_core
+  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_inner_core,npoin2D_eta_inner_core
+
+  integer ichunk,iproc_xi,iproc_eta
+
+!ADJOINT
+  real(kind=CUSTOM_REAL) b_two_omega_earth
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ROT_ADJOINT) :: &
+    b_A_array_rotation,b_B_array_rotation
+
+  double precision :: time_start
+
+! parameters read from parameter file
+  integer MIN_ATTENUATION_PERIOD,MAX_ATTENUATION_PERIOD,NER_CRUST, &
+          NER_80_MOHO,NER_220_80,NER_400_220,NER_600_400,NER_670_600,NER_771_670, &
+          NER_TOPDDOUBLEPRIME_771,NER_CMB_TOPDDOUBLEPRIME,NER_OUTER_CORE, &
+          NER_TOP_CENTRAL_CUBE_ICB,NEX_XI,NEX_ETA, &
+          NTSTEP_BETWEEN_OUTPUT_SEISMOS,&
+          NTSTEP_BETWEEN_READ_ADJSRC,NSTEP,NSOURCES,NTSTEP_BETWEEN_FRAMES, &
+          NTSTEP_BETWEEN_OUTPUT_INFO,NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN,SIMULATION_TYPE, &
+          MOVIE_VOLUME_TYPE,MOVIE_START,MOVIE_STOP,NOISE_TOMOGRAPHY
+
+  double precision DT,ROCEAN,RMIDDLE_CRUST, &
+          RMOHO,R80,R220,R400,R600,R670,R771,RTOPDDOUBLEPRIME,RCMB,RICB, &
+          RHO_TOP_OC,RHO_BOTTOM_OC,RHO_OCEANS,HDUR_MOVIE, &
+          MOVIE_TOP,MOVIE_BOTTOM,MOVIE_WEST,MOVIE_EAST,MOVIE_NORTH,MOVIE_SOUTH, &
+          ANGULAR_WIDTH_XI_IN_DEGREES
+
+  logical ONE_CRUST,TOPOGRAPHY,MOVIE_SURFACE,MOVIE_VOLUME,MOVIE_COARSE, &
+          RECEIVERS_CAN_BE_BURIED,PRINT_SOURCE_TIME_FUNCTION, &
+          SAVE_MESH_FILES,ABSORBING_CONDITIONS,INCLUDE_CENTRAL_CUBE,SAVE_FORWARD, &
+          OUTPUT_SEISMOS_ASCII_TEXT,OUTPUT_SEISMOS_SAC_ALPHANUM,OUTPUT_SEISMOS_SAC_BINARY, &
+          ROTATE_SEISMOGRAMS_RT,HONOR_1D_SPHERICAL_MOHO,WRITE_SEISMOGRAMS_BY_MASTER,&
+          SAVE_ALL_SEISMOS_IN_ONE_FILE,USE_BINARY_FOR_LARGE_FILE
+
+  character(len=150) OUTPUT_FILES,LOCAL_PATH
+
+!  logical COMPUTE_AND_STORE_STRAIN
+
+! for SAC headers for seismograms
+  integer yr_SAC,jda_SAC,ho_SAC,mi_SAC
+  real mb_SAC
+  double precision t_cmt_SAC,t_shift_SAC,elat_SAC,elon_SAC,depth_SAC, &
+    cmt_lat_SAC,cmt_lon_SAC,cmt_depth_SAC,cmt_hdur_SAC,sec_SAC
+  character(len=20) event_name_SAC
+
+! this for all the regions
+  integer, dimension(MAX_NUM_REGIONS) :: NSPEC2DMAX_XMIN_XMAX,NSPEC2DMAX_YMIN_YMAX, &
+               NSPEC2D_BOTTOM,NSPEC2D_TOP, &
+               NGLOB1D_RADIAL, &
+               NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX
+
+  character(len=150) prname
+
+!daniel: debugging
+!  character(len=256) :: filename
+!  logical, parameter :: SNAPSHOT_INNER_CORE = .true.
+
+! lookup table every km for gravity
+  real(kind=CUSTOM_REAL) minus_g_cmb,minus_g_icb
+  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table, &
+    minus_deriv_gravity_table,density_table,d_ln_density_dr_table,minus_rho_g_over_kappa_fluid
+
+! dummy array that does not need to be actually read
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,1) :: dummy_array
+
+! computed in read_compute_parameters
+  integer, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: ner,ratio_sampling_array
+  integer, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: doubling_index
+  double precision, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: r_bottom,r_top
+  logical, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: this_region_has_a_doubling
+  double precision, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: rmins,rmaxs
+
+! Boundary Mesh and Kernels
+  integer k_top,k_bot,iregion_code
+  integer, dimension(NSPEC2D_MOHO) :: ibelm_moho_top,ibelm_moho_bot
+  integer, dimension(NSPEC2D_400) :: ibelm_400_top,ibelm_400_bot
+  integer, dimension(NSPEC2D_670) :: ibelm_670_top,ibelm_670_bot
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_MOHO) :: normal_moho
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_400) :: normal_400
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_670) :: normal_670
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_MOHO) :: moho_kl, moho_kl_top, moho_kl_bot
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_400) :: d400_kl, d400_kl_top, d400_kl_bot
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_670) ::  d670_kl, d670_kl_top, d670_kl_bot
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_CMB) :: cmb_kl, cmb_kl_top, cmb_kl_bot
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_ICB) :: icb_kl, icb_kl_top, icb_kl_bot
+  logical :: fluid_solid_boundary
+
+  integer :: i,ier
+
+! NOISE_TOMOGRAPHY
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:), allocatable :: noise_sourcearray
+  real(kind=CUSTOM_REAL), dimension(:), allocatable :: &
+             normal_x_noise,normal_y_noise,normal_z_noise, mask_noise
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:), allocatable :: noise_surface_movie
+  integer :: irec_master_noise
+
+#ifdef _HANDOPT
+  integer :: imodulo_NGLOB_CRUST_MANTLE,imodulo_NGLOB_CRUST_MANTLE4, &
+            imodulo_NGLOB_INNER_CORE 
+#endif
+
+! ************** PROGRAM STARTS HERE **************
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+! trivia about the programming style adopted here:
+!
+! note 1: for performance reasons, we try to use as much from the stack memory as possible.
+!             This is done to avoid memory fragmentation and also to optimize performance.
+!             Stack memory is a place in computer memory where all the variables that are declared
+!             and initialized **before** runtime are stored. Our static array allocation will use that one.
+!             All variables declared within our main routine also will be stored on the stack.
+!
+!             the heap is the section of computer memory where all the variables created or initialized
+!             **at** runtime are stored. it is used for dynamic memory allocation.
+!
+!             stack is much faster than the heap.
+!
+!             when calling a function, additional storage will be allocated for the variables in that function.
+!             that storage will be allocated in the heap memory segment.
+!
+!             most routine calls here will have rather long argument lists, probably because of this performance criteria.
+!             using modules/common data blocks together with dynamic allocation will put data into heap memory,
+!             thus it has longer latency to access variables than stack memory variables.
+!
+!             however, declaring the static arrays needed in compute_forces_crust_mantle_Dev()
+!             like e.g. sum_terms, tempx1,...B1_m1_m2_5points,... in this main routine and
+!             passing them along as arguments to the routine makes the code slower.
+!             it seems that this stack/heap criterion is more complicated.
+!
+!             another reason why modules are avoided is to make the code thread safe.
+!             having different threads access the same data structure and modifying it at the same time
+!             would lead to problems. passing arguments is a way to avoid such complications.
+!
+! note 2: Most of the computation time is spent
+!             inside the time loop (mainly in the compute_forces_crust_mantle_Dev() routine).
+!             Any code performance tuning will be most effective in there.
+!
+! note 3: Fortran is a code language that uses column-first ordering for arrays,
+!             e.g., it stores a(i,j) in this order: a(1,1),a(2,1),a(3,1),...,a(1,2),a(2,2),a(3,2),..
+!             it is therefore more efficient to have the inner-loop over i, and the outer loop over j
+!
+! note 4: Deville et al. (2002) routines significantly reduce the total number of memory accesses
+!             required to perform matrix-matrix products at the spectral element level.
+!             For most compilers and hardware, will result in a significant speedup (> 30% or more, sometimes twice faster).
+!
+! note 5: a common technique to help compilers enhance pipelining is loop unrolling. We do this here in a simple
+!             and straigthforward way, so don't be confused about the do-loop writing. For this to take effect, 
+!             you have to turn the hand-optimization flag on: compile with additional flag -D_HANDOPT
+!
+! note 6: whenever adding some new code, please make sure to use
+!             spaces rather than tabs. Tabulators are in principle not allowed in Fortran95.
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+  ! initialize the MPI communicator and start the NPROCTOT MPI processes.
+  call MPI_INIT(ier)
+
+  ! force Flush-To-Zero if available to avoid very slow Gradual Underflow trapping
+  call force_ftz()
+
+  ! initializes simulation parameters
+  call initialize_simulation(myrank,MIN_ATTENUATION_PERIOD,MAX_ATTENUATION_PERIOD,NER_CRUST, &
+                NER_80_MOHO,NER_220_80,NER_400_220,NER_600_400,NER_670_600,NER_771_670, &
+                NER_TOPDDOUBLEPRIME_771,NER_CMB_TOPDDOUBLEPRIME,NER_OUTER_CORE, &
+                NER_TOP_CENTRAL_CUBE_ICB,ANGULAR_WIDTH_XI_IN_DEGREES,NEX_XI,NEX_ETA, &
+                NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
+                NTSTEP_BETWEEN_READ_ADJSRC,NSTEP,NSOURCES,NTSTEP_BETWEEN_FRAMES, &
+                NTSTEP_BETWEEN_OUTPUT_INFO,NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN,SIMULATION_TYPE, &
+                DT,ROCEAN,RMIDDLE_CRUST,RMOHO,R80,R220,R400,R600,R670,R771,&
+                RTOPDDOUBLEPRIME,RCMB,RICB, &
+                RHO_TOP_OC,RHO_BOTTOM_OC,RHO_OCEANS, &
+                MOVIE_VOLUME_TYPE,MOVIE_START,MOVIE_STOP, &
+                HDUR_MOVIE,MOVIE_TOP,MOVIE_BOTTOM,MOVIE_WEST,MOVIE_EAST, &
+                MOVIE_NORTH,MOVIE_SOUTH,MOVIE_SURFACE,MOVIE_VOLUME, &
+                RECEIVERS_CAN_BE_BURIED,PRINT_SOURCE_TIME_FUNCTION, &
+                SAVE_MESH_FILES,ABSORBING_CONDITIONS,INCLUDE_CENTRAL_CUBE,SAVE_FORWARD, &
+                SAVE_ALL_SEISMOS_IN_ONE_FILE,MOVIE_COARSE,OUTPUT_SEISMOS_ASCII_TEXT, &
+                OUTPUT_SEISMOS_SAC_ALPHANUM,OUTPUT_SEISMOS_SAC_BINARY, &
+                ROTATE_SEISMOGRAMS_RT,WRITE_SEISMOGRAMS_BY_MASTER,USE_BINARY_FOR_LARGE_FILE, &
+                LOCAL_PATH,OUTPUT_FILES, &
+                ratio_sampling_array, ner, doubling_index,r_bottom,r_top, &
+                this_region_has_a_doubling,rmins,rmaxs, &
+                TOPOGRAPHY,HONOR_1D_SPHERICAL_MOHO,ONE_CRUST, &
+                nspl,rspl,espl,espl2,ibathy_topo, &
+                NSPEC2DMAX_XMIN_XMAX,NSPEC2DMAX_YMIN_YMAX,NSPEC2D_BOTTOM,NSPEC2D_TOP, &
+                NGLOB1D_RADIAL,NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX, &
+                xigll,yigll,zigll,wxgll,wygll,wzgll,wgll_cube, &
+                hprime_xx,hprime_yy,hprime_zz,hprime_xxT, &
+                hprimewgll_xx,hprimewgll_yy,hprimewgll_zz,hprimewgll_xxT, &
+                wgllwgll_xy,wgllwgll_xz,wgllwgll_yz, &
+                rec_filename,STATIONS,nrec,NOISE_TOMOGRAPHY)
+
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+! starts reading the databases
+  call read_mesh_databases(myrank,rho_vp_crust_mantle,rho_vs_crust_mantle, &
+              xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+              xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+              etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+              gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+              rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
+              kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+              nspec_iso,nspec_tiso,nspec_ani, &
+              c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+              c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+              c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+              c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+              c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+              c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+              c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+              ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+            ! -- idoubling_crust_mantle,
+              is_on_a_slice_edge_crust_mantle,rmass_crust_mantle,rmass_ocean_load, &
+              vp_outer_core,xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+              xix_outer_core,xiy_outer_core,xiz_outer_core, &
+              etax_outer_core,etay_outer_core,etaz_outer_core, &
+              gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+              rhostore_outer_core,kappavstore_outer_core, &
+              ibool_outer_core,idoubling_outer_core,ispec_is_tiso_outer_core, &
+              is_on_a_slice_edge_outer_core,rmass_outer_core, &
+              xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+              xix_inner_core,xiy_inner_core,xiz_inner_core, &
+              etax_inner_core,etay_inner_core,etaz_inner_core, &
+              gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+              rhostore_inner_core,kappavstore_inner_core,muvstore_inner_core, &
+              c11store_inner_core,c12store_inner_core,c13store_inner_core, &
+              c33store_inner_core,c44store_inner_core, &
+              ibool_inner_core,idoubling_inner_core,ispec_is_tiso_inner_core, &
+              is_on_a_slice_edge_inner_core,rmass_inner_core, &
+              ABSORBING_CONDITIONS,LOCAL_PATH)
+
+  ! read 2-D addressing for summation between slices with MPI
+  call read_mesh_databases_addressing(myrank, &
+              iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
+              iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+              npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+              iboolfaces_crust_mantle,npoin2D_faces_crust_mantle, &
+              iboolcorner_crust_mantle, &
+              iboolleft_xi_outer_core,iboolright_xi_outer_core, &
+              iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+              npoin2D_xi_outer_core,npoin2D_eta_outer_core,&
+              iboolfaces_outer_core,npoin2D_faces_outer_core, &
+              iboolcorner_outer_core, &
+              iboolleft_xi_inner_core,iboolright_xi_inner_core, &
+              iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+              npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+              iboolfaces_inner_core,npoin2D_faces_inner_core, &
+              iboolcorner_inner_core, &
+              iprocfrom_faces,iprocto_faces,imsg_type, &
+              iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+              LOCAL_PATH,OUTPUT_FILES, &
+              NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX,NGLOB1D_RADIAL, &
+              NGLOB2DMAX_XY,NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
+              addressing,ichunk_slice,iproc_xi_slice,iproc_eta_slice, &
+              ichunk,iproc_xi,iproc_eta)
+
+  ! to couple mantle with outer core
+  call read_mesh_databases_coupling(myrank, &
+              nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle, &
+              nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle, &
+              ibelm_xmin_crust_mantle,ibelm_xmax_crust_mantle,ibelm_ymin_crust_mantle, &
+              ibelm_ymax_crust_mantle,ibelm_bottom_crust_mantle,ibelm_top_crust_mantle, &
+              normal_xmin_crust_mantle,normal_xmax_crust_mantle,normal_ymin_crust_mantle, &
+              normal_ymax_crust_mantle,normal_bottom_crust_mantle,normal_top_crust_mantle, &
+              jacobian2D_xmin_crust_mantle,jacobian2D_xmax_crust_mantle,jacobian2D_ymin_crust_mantle, &
+              jacobian2D_ymax_crust_mantle,jacobian2D_bottom_crust_mantle,jacobian2D_top_crust_mantle, &
+              nspec2D_xmin_outer_core,nspec2D_xmax_outer_core, &
+              nspec2D_ymin_outer_core,nspec2D_ymax_outer_core, &
+              ibelm_xmin_outer_core,ibelm_xmax_outer_core,ibelm_ymin_outer_core, &
+              ibelm_ymax_outer_core,ibelm_bottom_outer_core,ibelm_top_outer_core, &
+              normal_xmin_outer_core,normal_xmax_outer_core,normal_ymin_outer_core, &
+              normal_ymax_outer_core,normal_bottom_outer_core,normal_top_outer_core, &
+              jacobian2D_xmin_outer_core,jacobian2D_xmax_outer_core,jacobian2D_ymin_outer_core, &
+              jacobian2D_ymax_outer_core,jacobian2D_bottom_outer_core,jacobian2D_top_outer_core, &
+              nspec2D_xmin_inner_core,nspec2D_xmax_inner_core, &
+              nspec2D_ymin_inner_core,nspec2D_ymax_inner_core, &
+              ibelm_xmin_inner_core,ibelm_xmax_inner_core,ibelm_ymin_inner_core, &
+              ibelm_ymax_inner_core,ibelm_bottom_inner_core,ibelm_top_inner_core, &
+              ibelm_moho_top,ibelm_moho_bot,ibelm_400_top,ibelm_400_bot, &
+              ibelm_670_top,ibelm_670_bot,normal_moho,normal_400,normal_670, &
+              k_top,k_bot,moho_kl,d400_kl,d670_kl,cmb_kl,icb_kl, &
+              LOCAL_PATH,SIMULATION_TYPE)
+
+! added this to reduce the size of the buffers
+! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
+  npoin2D_max_all_CM_IC = max(maxval(npoin2D_xi_crust_mantle(:) + npoin2D_xi_inner_core(:)), &
+                        maxval(npoin2D_eta_crust_mantle(:) + npoin2D_eta_inner_core(:)))
+
+  allocate(buffer_send_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED), &
+          buffer_received_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED),stat=ier)
+  if( ier /= 0 ) call exit_MPI(myrank,'error allocating mpi buffer')
+
+  allocate(b_buffer_send_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED), &
+          b_buffer_received_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED),stat=ier)
+  if( ier /= 0 ) call exit_MPI(myrank,'error allocating mpi b_buffer')
+
+  call fix_non_blocking_slices(is_on_a_slice_edge_crust_mantle,iboolright_xi_crust_mantle, &
+         iboolleft_xi_crust_mantle,iboolright_eta_crust_mantle,iboolleft_eta_crust_mantle, &
+         npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle,ibool_crust_mantle, &
+         mask_ibool,NSPEC_CRUST_MANTLE,NGLOB_CRUST_MANTLE,NGLOB2DMAX_XMIN_XMAX_CM,NGLOB2DMAX_YMIN_YMAX_CM)
+
+  call fix_non_blocking_slices(is_on_a_slice_edge_outer_core,iboolright_xi_outer_core, &
+         iboolleft_xi_outer_core,iboolright_eta_outer_core,iboolleft_eta_outer_core, &
+         npoin2D_xi_outer_core,npoin2D_eta_outer_core,ibool_outer_core, &
+         mask_ibool,NSPEC_OUTER_CORE,NGLOB_OUTER_CORE,NGLOB2DMAX_XMIN_XMAX_OC,NGLOB2DMAX_YMIN_YMAX_OC)
+
+  call fix_non_blocking_slices(is_on_a_slice_edge_inner_core,iboolright_xi_inner_core, &
+         iboolleft_xi_inner_core,iboolright_eta_inner_core,iboolleft_eta_inner_core, &
+         npoin2D_xi_inner_core,npoin2D_eta_inner_core,ibool_inner_core, &
+         mask_ibool,NSPEC_INNER_CORE,NGLOB_INNER_CORE,NGLOB2DMAX_XMIN_XMAX_IC,NGLOB2DMAX_YMIN_YMAX_IC)
+
+  ! absorbing boundaries
+  if(ABSORBING_CONDITIONS) then
+    ! crust_mantle
+    if (nspec2D_xmin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_xmin_cm = nspec2D_xmin_crust_mantle
+    else
+      nabs_xmin_cm = 1
+    endif
+    allocate(absorb_xmin_crust_mantle5(NDIM,NGLLY,NGLLZ,nabs_xmin_cm,8),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmin')
+
+    if (nspec2D_xmax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_xmax_cm = nspec2D_xmax_crust_mantle
+    else
+      nabs_xmax_cm = 1
+    endif
+    allocate(absorb_xmax_crust_mantle5(NDIM,NGLLY,NGLLZ,nabs_xmax_cm,8),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmax')
+
+    if (nspec2D_ymin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_ymin_cm = nspec2D_ymin_crust_mantle
+    else
+      nabs_ymin_cm = 1
+    endif
+    allocate(absorb_ymin_crust_mantle5(NDIM,NGLLX,NGLLZ,nabs_ymin_cm,8),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymin')
+
+    if (nspec2D_ymax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_ymax_cm = nspec2D_ymax_crust_mantle
+    else
+      nabs_ymax_cm = 1
+    endif
+    allocate(absorb_ymax_crust_mantle5(NDIM,NGLLX,NGLLZ,nabs_ymax_cm,8),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymax')
+
+    ! outer_core
+    if (nspec2D_xmin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_xmin_oc = nspec2D_xmin_outer_core
+    else
+      nabs_xmin_oc = 1
+    endif
+    allocate(absorb_xmin_outer_core(NGLLY,NGLLZ,nabs_xmin_oc),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmin')
+
+    if (nspec2D_xmax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_xmax_oc = nspec2D_xmax_outer_core
+    else
+      nabs_xmax_oc = 1
+    endif
+    allocate(absorb_xmax_outer_core(NGLLY,NGLLZ,nabs_xmax_oc),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmax')
+
+    if (nspec2D_ymin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_ymin_oc = nspec2D_ymin_outer_core
+    else
+      nabs_ymin_oc = 1
+    endif
+    allocate(absorb_ymin_outer_core(NGLLX,NGLLZ,nabs_ymin_oc),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymin')
+
+    if (nspec2D_ymax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_ymax_oc = nspec2D_ymax_outer_core
+    else
+      nabs_ymax_oc = 1
+    endif
+    allocate(absorb_ymax_outer_core(NGLLX,NGLLZ,nabs_ymax_oc),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymax')
+
+    if (NSPEC2D_BOTTOM(IREGION_OUTER_CORE) > 0 .and. &
+       (SIMULATION_TYPE == 3 .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      nabs_zmin_oc = NSPEC2D_BOTTOM(IREGION_OUTER_CORE)
+    else
+      nabs_zmin_oc = 1
+    endif
+    allocate(absorb_zmin_outer_core(NGLLX,NGLLY,nabs_zmin_oc),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb zmin')
+
+    ! read arrays for Stacey conditions
+    call read_mesh_databases_stacey(myrank, &
+                      nimin_crust_mantle,nimax_crust_mantle,njmin_crust_mantle, &
+                      njmax_crust_mantle,nkmin_xi_crust_mantle,nkmin_eta_crust_mantle, &
+                      nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle, &
+                      nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle, &
+                      reclen_xmin_crust_mantle,reclen_xmax_crust_mantle, &
+                      reclen_ymin_crust_mantle,reclen_ymax_crust_mantle, &
+                      nimin_outer_core,nimax_outer_core,njmin_outer_core, &
+                      njmax_outer_core,nkmin_xi_outer_core,nkmin_eta_outer_core, &
+                      nspec2D_xmin_outer_core,nspec2D_xmax_outer_core, &
+                      nspec2D_ymin_outer_core,nspec2D_ymax_outer_core, &
+                      reclen_xmin_outer_core,reclen_xmax_outer_core, &
+                      reclen_ymin_outer_core,reclen_ymax_outer_core, &
+                      reclen_zmin,NSPEC2D_BOTTOM, &
+                      SIMULATION_TYPE,SAVE_FORWARD,LOCAL_PATH,NSTEP)
+
+  endif
+
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+! source and receivers
+
+  ! allocate arrays for source
+  allocate(islice_selected_source(NSOURCES), &
+          ispec_selected_source(NSOURCES), &
+          Mxx(NSOURCES), &
+          Myy(NSOURCES), &
+          Mzz(NSOURCES), &
+          Mxy(NSOURCES), &
+          Mxz(NSOURCES), &
+          Myz(NSOURCES), &
+          xi_source(NSOURCES), &
+          eta_source(NSOURCES), &
+          gamma_source(NSOURCES), &
+          tshift_cmt(NSOURCES), &
+          hdur(NSOURCES), &
+          hdur_gaussian(NSOURCES), &
+          theta_source(NSOURCES), &
+          phi_source(NSOURCES), &
+          nu_source(NDIM,NDIM,NSOURCES),stat=ier)
+  if( ier /= 0 ) call exit_MPI(myrank,'error allocating source arrays')
+
+  ! allocate memory for receiver arrays
+  allocate(islice_selected_rec(nrec), &
+          ispec_selected_rec(nrec), &
+          xi_receiver(nrec), &
+          eta_receiver(nrec), &
+          gamma_receiver(nrec), &
+          station_name(nrec), &
+          network_name(nrec), &
+          stlat(nrec), &
+          stlon(nrec), &
+          stele(nrec), &
+          stbur(nrec), &
+          nu(NDIM,NDIM,nrec),stat=ier)
+  if( ier /= 0 ) call exit_MPI(myrank,'error allocating receiver arrays')
+
+  ! locates sources and receivers
+  call setup_sources_receivers(NSOURCES,myrank,ibool_crust_mantle, &
+                      xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+                      xigll,yigll,zigll,TOPOGRAPHY, &
+                      sec,tshift_cmt,theta_source,phi_source, &
+                      NSTEP,DT,hdur,hdur_gaussian,t0,Mxx,Myy,Mzz,Mxy,Mxz,Myz, &
+                      islice_selected_source,ispec_selected_source, &
+                      xi_source,eta_source,gamma_source,nu_source, &
+                      rspl,espl,espl2,nspl,ibathy_topo,NEX_XI,PRINT_SOURCE_TIME_FUNCTION, &
+                      rec_filename,nrec,islice_selected_rec,ispec_selected_rec, &
+                      xi_receiver,eta_receiver,gamma_receiver,station_name,network_name, &
+                      stlat,stlon,stele,stbur,nu, &
+                      nrec_local,nadj_rec_local,nrec_simulation, &
+                      SIMULATION_TYPE,RECEIVERS_CAN_BE_BURIED,MOVIE_SURFACE,MOVIE_VOLUME, &
+                      HDUR_MOVIE,OUTPUT_FILES,LOCAL_PATH)
+
+  ! allocates source arrays
+  if (SIMULATION_TYPE == 1  .or. SIMULATION_TYPE == 3) then
+    allocate(sourcearrays(NDIM,NGLLX,NGLLY,NGLLZ,NSOURCES),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating sourcearrays')
+
+    ! stores source arrays
+    call setup_sources_receivers_srcarr(NSOURCES,myrank, &
+                      ispec_selected_source,islice_selected_source, &
+                      xi_source,eta_source,gamma_source, &
+                      Mxx,Myy,Mzz,Mxy,Mxz,Myz, &
+                      xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                      etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+                      gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+                      xigll,yigll,zigll,sourcearrays)
+  endif
+
+
+  if (SIMULATION_TYPE == 2 .or. SIMULATION_TYPE == 3) then
+    NSTEP_SUB_ADJ = ceiling( dble(NSTEP)/dble(NTSTEP_BETWEEN_READ_ADJSRC) )
+    allocate(iadj_vec(NSTEP),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating iadj_vec')
+
+    ! initializes iadj_vec
+    do it=1,NSTEP
+       iadj_vec(it) = NSTEP-it+1  ! default is for reversing entire record
+    enddo
+
+    if(nadj_rec_local > 0) then
+      ! allocate adjoint source arrays
+      allocate(adj_sourcearrays(NDIM,NGLLX,NGLLY,NGLLZ,nadj_rec_local,NTSTEP_BETWEEN_READ_ADJSRC),stat=ier)
+      if( ier /= 0 ) call exit_MPI(myrank,'error allocating adjoint sourcearrays')
+      adj_sourcearrays(:,:,:,:,:,:) = 0._CUSTOM_REAL
+
+      ! allocate indexing arrays
+      allocate(iadjsrc(NSTEP_SUB_ADJ,2), &
+              iadjsrc_len(NSTEP_SUB_ADJ),stat=ier)
+      if( ier /= 0 ) call exit_MPI(myrank,'error allocating adjoint indexing arrays')
+      ! initializes iadjsrc, iadjsrc_len and iadj_vec
+      call setup_sources_receivers_adjindx(NSTEP,NSTEP_SUB_ADJ, &
+                      NTSTEP_BETWEEN_READ_ADJSRC, &
+                      iadjsrc,iadjsrc_len,iadj_vec)
+    endif
+  endif
+
+  ! allocates receiver interpolators
+  if (nrec_local > 0) then
+    ! allocate Lagrange interpolators for receivers
+    allocate(hxir_store(nrec_local,NGLLX), &
+            hetar_store(nrec_local,NGLLY), &
+            hgammar_store(nrec_local,NGLLZ),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating receiver interpolators')
+    ! define local to global receiver numbering mapping
+    allocate(number_receiver_global(nrec_local),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating global receiver numbering')
+    ! define and store Lagrange interpolators at all the receivers
+    if (SIMULATION_TYPE == 2) then
+      nadj_hprec_local = nrec_local
+    else
+      nadj_hprec_local = 1
+    endif
+    allocate(hpxir_store(nadj_hprec_local,NGLLX), &
+            hpetar_store(nadj_hprec_local,NGLLY), &
+            hpgammar_store(nadj_hprec_local,NGLLZ),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating derivative interpolators')
+
+    ! stores interpolators for receiver positions
+    call setup_sources_receivers_intp(NSOURCES,myrank, &
+                      islice_selected_source, &
+                      xi_source,eta_source,gamma_source, &
+                      xigll,yigll,zigll, &
+                      SIMULATION_TYPE,nrec,nrec_local, &
+                      islice_selected_rec,number_receiver_global, &
+                      xi_receiver,eta_receiver,gamma_receiver, &
+                      hxir_store,hetar_store,hgammar_store, &
+                      nadj_hprec_local,hpxir_store,hpetar_store,hpgammar_store)
+
+    ! allocate seismogram array
+    if (SIMULATION_TYPE == 1 .or. SIMULATION_TYPE == 3) then
+      allocate(seismograms(NDIM,nrec_local,NTSTEP_BETWEEN_OUTPUT_SEISMOS),stat=ier)
+      if(ier /= 0) stop 'error while allocating seismograms'
+    else
+      allocate(seismograms(NDIM*NDIM,nrec_local,NTSTEP_BETWEEN_OUTPUT_SEISMOS),stat=ier)
+      if(ier /= 0) stop 'error while allocating seismograms'
+      ! allocate Frechet derivatives array
+      allocate(moment_der(NDIM,NDIM,nrec_local),sloc_der(NDIM,nrec_local), &
+              stshift_der(nrec_local),shdur_der(nrec_local),stat=ier)
+      if( ier /= 0 ) call exit_MPI(myrank,'error allocating frechet derivatives arrays')
+
+      moment_der(:,:,:) = 0._CUSTOM_REAL
+      sloc_der(:,:) = 0._CUSTOM_REAL
+      stshift_der(:) = 0._CUSTOM_REAL
+      shdur_der(:) = 0._CUSTOM_REAL
+
+    endif
+    ! initialize seismograms
+    seismograms(:,:,:) = 0._CUSTOM_REAL
+    nit_written = 0
+  else
+    ! allocate dummy array since we need it to pass as argument e.g. in write_seismograms() routine
+    ! note: nrec_local is zero, fortran 90/95 should allow zero-sized array allocation...
+    allocate(seismograms(NDIM,nrec_local,NTSTEP_BETWEEN_OUTPUT_SEISMOS),stat=ier)
+    if( ier /= 0) stop 'error while allocating zero seismograms'
+    allocate(number_receiver_global(nrec_local),stat=ier)
+    if( ier /= 0) stop 'error while allocating zero number_receiver_global'
+  endif
+
+  ! get information about event name and location for SAC seismograms
+
+  ! The following line is added for get_event_info subroutine.
+  ! Because the way NSOURCES_SAC was declared has been changed.
+  ! The rest of the changes in this program is just the updates of the subroutines that
+  ! I did changes, e.g., adding/removing parameters. by Ebru Bozdag
+  call get_event_info_parallel(myrank,yr_SAC,jda_SAC,ho_SAC,mi_SAC,sec_SAC,&
+                              event_name_SAC,t_cmt_SAC,t_shift_SAC, &
+                              elat_SAC,elon_SAC,depth_SAC,mb_SAC,cmt_lat_SAC,&
+                              cmt_lon_SAC,cmt_depth_SAC,cmt_hdur_SAC,NSOURCES)
+
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+
+  ! user output
+  if(myrank == 0) then
+
+    write(IMAIN,*)
+    write(IMAIN,*) 'Reference radius of the Earth used is ',R_EARTH_KM,' km'
+    write(IMAIN,*)
+
+    write(IMAIN,*)
+    if(OCEANS_VAL) then
+      write(IMAIN,*) 'incorporating the oceans using equivalent load'
+    else
+      write(IMAIN,*) 'no oceans'
+    endif
+
+    write(IMAIN,*)
+    if(ELLIPTICITY_VAL) then
+      write(IMAIN,*) 'incorporating ellipticity'
+    else
+      write(IMAIN,*) 'no ellipticity'
+    endif
+
+    write(IMAIN,*)
+    if(TOPOGRAPHY) then
+      write(IMAIN,*) 'incorporating surface topography'
+    else
+      write(IMAIN,*) 'no surface topography'
+    endif
+
+    write(IMAIN,*)
+    if(GRAVITY_VAL) then
+      write(IMAIN,*) 'incorporating self-gravitation (Cowling approximation)'
+    else
+      write(IMAIN,*) 'no self-gravitation'
+    endif
+
+    write(IMAIN,*)
+    if(ROTATION_VAL) then
+      write(IMAIN,*) 'incorporating rotation'
+    else
+      write(IMAIN,*) 'no rotation'
+    endif
+
+    write(IMAIN,*)
+    if(ATTENUATION_VAL) then
+      write(IMAIN,*) 'incorporating attenuation using ',N_SLS,' standard linear solids'
+
+      if(ATTENUATION_3D_VAL) write(IMAIN,*) 'using 3D attenuation'
+
+      if(USE_ATTENUATION_MIMIC ) write(IMAIN,*) 'mimicking effects on velocity only'
+    else
+      write(IMAIN,*) 'no attenuation'
+    endif
+
+    write(IMAIN,*)
+    write(IMAIN,*)
+    write(IMAIN,*)
+
+  endif
+
+  ! the mass matrix needs to be assembled with MPI here once and for all
+  call prepare_timerun_rmass(myrank,rmass_ocean_load,rmass_crust_mantle, &
+                      rmass_outer_core,rmass_inner_core, &
+                      iproc_xi,iproc_eta,ichunk,addressing, &
+                      iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
+                      iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+                      npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+                      iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+                      iboolleft_xi_outer_core,iboolright_xi_outer_core, &
+                      iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+                      npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+                      iboolfaces_outer_core,iboolcorner_outer_core, &
+                      iboolleft_xi_inner_core,iboolright_xi_inner_core, &
+                      iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+                      npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+                      iboolfaces_inner_core,iboolcorner_inner_core, &
+                      iprocfrom_faces,iprocto_faces,imsg_type, &
+                      iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+                      buffer_send_faces,buffer_received_faces, &
+                      buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
+                      NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
+                      NGLOB1D_RADIAL,NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX,NGLOB2DMAX_XY,npoin2D_max_all_CM_IC)
+
+  ! mass matrix including central cube
+  if(INCLUDE_CENTRAL_CUBE) then
+
+    if(myrank == 0) write(IMAIN,*) 'including central cube'
+
+    ! compute number of messages to expect in cube as well as their size
+    call comp_central_cube_buffer_size(iproc_xi,iproc_eta,ichunk, &
+                NPROC_XI_VAL,NPROC_ETA_VAL,NSPEC2D_BOTTOM(IREGION_INNER_CORE), &
+                nb_msgs_theor_in_cube,npoin2D_cube_from_slices)
+
+    ! this value is used for dynamic memory allocation, therefore make sure it is never zero
+    if(nb_msgs_theor_in_cube > 0) then
+      non_zero_nb_msgs_theor_in_cube = nb_msgs_theor_in_cube
+    else
+      non_zero_nb_msgs_theor_in_cube = 1
+    endif
+
+    ! allocate buffers for cube and slices
+    allocate(sender_from_slices_to_cube(non_zero_nb_msgs_theor_in_cube), &
+            buffer_all_cube_from_slices(non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices,NDIM), &
+            b_buffer_all_cube_from_slices(non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices,NDIM), &
+            buffer_slices(npoin2D_cube_from_slices,NDIM), &
+            b_buffer_slices(npoin2D_cube_from_slices,NDIM), &
+            buffer_slices2(npoin2D_cube_from_slices,NDIM), &
+            ibool_central_cube(non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating cube buffers')
+
+    ! handles the communications with the central cube if it was included in the mesh
+    call prepare_timerun_centralcube(myrank,rmass_inner_core, &
+                      iproc_xi,iproc_eta,ichunk, &
+                      NSPEC2DMAX_XMIN_XMAX,NSPEC2DMAX_YMIN_YMAX,NSPEC2D_BOTTOM, &
+                      addressing,ibool_inner_core,idoubling_inner_core, &
+                      xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+                      nspec2D_xmin_inner_core,nspec2D_xmax_inner_core, &
+                      nspec2D_ymin_inner_core,nspec2D_ymax_inner_core, &
+                      ibelm_xmin_inner_core,ibelm_xmax_inner_core, &
+                      ibelm_ymin_inner_core,ibelm_ymax_inner_core,ibelm_bottom_inner_core, &
+                      nb_msgs_theor_in_cube,non_zero_nb_msgs_theor_in_cube, &
+                      npoin2D_cube_from_slices,receiver_cube_from_slices, &
+                      sender_from_slices_to_cube,ibool_central_cube, &
+                      buffer_slices,buffer_slices2,buffer_all_cube_from_slices)
+
+    call fix_non_blocking_central_cube(is_on_a_slice_edge_inner_core, &
+         ibool_inner_core,NSPEC_INNER_CORE,NGLOB_INNER_CORE,nb_msgs_theor_in_cube,ibelm_bottom_inner_core, &
+         idoubling_inner_core,npoin2D_cube_from_slices,ibool_central_cube, &
+         NSPEC2D_BOTTOM(IREGION_INNER_CORE),ichunk)
+
+
+  else
+
+    ! allocate fictitious buffers for cube and slices with a dummy size
+    ! just to be able to use them as arguments in subroutine calls
+    allocate(sender_from_slices_to_cube(1), &
+            buffer_all_cube_from_slices(1,1,1), &
+            b_buffer_all_cube_from_slices(1,1,1), &
+            buffer_slices(1,1), &
+            b_buffer_slices(1,1), &
+            buffer_slices2(1,1), &
+            ibool_central_cube(1,1),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating dummy buffers')
+
+  endif
+
+  ! check that all the mass matrices are positive
+  if(OCEANS_VAL) then
+    if(minval(rmass_ocean_load) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the oceans')
+  endif
+  if(minval(rmass_crust_mantle) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the crust_mantle')
+  if(minval(rmass_inner_core) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the inner core')
+  if(minval(rmass_outer_core) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the outer core')
+
+  ! for efficiency, invert final mass matrix once and for all on each slice
+  if(OCEANS_VAL) rmass_ocean_load = 1._CUSTOM_REAL / rmass_ocean_load
+  rmass_crust_mantle = 1._CUSTOM_REAL / rmass_crust_mantle
+  rmass_outer_core = 1._CUSTOM_REAL / rmass_outer_core
+  rmass_inner_core = 1._CUSTOM_REAL / rmass_inner_core
+
+
+  ! change x, y, z to r, theta and phi once and for all
+  ! IMPROVE dangerous: old name kept (xstore ystore zstore) for new values
+
+  ! convert in the crust and mantle
+  do i = 1,NGLOB_CRUST_MANTLE
+    call xyz_2_rthetaphi(xstore_crust_mantle(i), &
+                        ystore_crust_mantle(i), &
+                        zstore_crust_mantle(i),rval,thetaval,phival)
+    xstore_crust_mantle(i) = rval
+    ystore_crust_mantle(i) = thetaval
+    zstore_crust_mantle(i) = phival
+  enddo
+
+  ! convert in the outer core
+  do i = 1,NGLOB_OUTER_CORE
+    call xyz_2_rthetaphi(xstore_outer_core(i), &
+                        ystore_outer_core(i), &
+                        zstore_outer_core(i),rval,thetaval,phival)
+    xstore_outer_core(i) = rval
+    ystore_outer_core(i) = thetaval
+    zstore_outer_core(i) = phival
+  enddo
+
+  ! convert in the inner core
+  do i = 1,NGLOB_INNER_CORE
+    call xyz_2_rthetaphi(xstore_inner_core(i), &
+                        ystore_inner_core(i), &
+                        zstore_inner_core(i),rval,thetaval,phival)
+    xstore_inner_core(i) = rval
+    ystore_inner_core(i) = thetaval
+    zstore_inner_core(i) = phival
+  enddo
+
+  ! allocate files to save movies
+  if(MOVIE_SURFACE .or. NOISE_TOMOGRAPHY /=0) then    ! for noise tomography, store_val_x/y/z/ux/uy/uz needed for 'surface movie'
+    if(MOVIE_COARSE .and. NOISE_TOMOGRAPHY ==0) then  ! only output corners !for noise tomography, must NOT be coarse
+       nmovie_points = 2 * 2 * NSPEC2D_TOP(IREGION_CRUST_MANTLE)
+       if(NGLLX /= NGLLY) &
+        call exit_MPI(myrank,'MOVIE_COARSE together with MOVIE_SURFACE requires NGLLX=NGLLY')
+       NIT = NGLLX - 1
+    else
+       nmovie_points = NGLLX * NGLLY * NSPEC2D_TOP(IREGION_CRUST_MANTLE)
+       NIT = 1
+    endif
+    allocate(store_val_x(nmovie_points), &
+            store_val_y(nmovie_points), &
+            store_val_z(nmovie_points), &
+            store_val_ux(nmovie_points), &
+            store_val_uy(nmovie_points), &
+            store_val_uz(nmovie_points),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating movie surface arrays')
+
+    if (MOVIE_SURFACE) then  ! those arrays are not neccessary for noise tomography, so only allocate them in MOVIE_SURFACE case
+       allocate(store_val_x_all(nmovie_points,0:NPROCTOT_VAL-1), &
+              store_val_y_all(nmovie_points,0:NPROCTOT_VAL-1), &
+              store_val_z_all(nmovie_points,0:NPROCTOT_VAL-1), &
+              store_val_ux_all(nmovie_points,0:NPROCTOT_VAL-1), &
+              store_val_uy_all(nmovie_points,0:NPROCTOT_VAL-1), &
+              store_val_uz_all(nmovie_points,0:NPROCTOT_VAL-1),stat=ier)
+       if( ier /= 0 ) call exit_MPI(myrank,'error allocating movie surface all arrays')
+    endif
+    if(myrank == 0) then
+      write(IMAIN,*)
+      write(IMAIN,*) 'Movie surface:'
+      write(IMAIN,*) '  Writing to moviedata*** files in output directory'
+      if(MOVIE_VOLUME_TYPE == 5) then
+        write(IMAIN,*) '  movie output: displacement'
+      else
+        write(IMAIN,*) '  movie output: velocity'
+      endif
+      write(IMAIN,*) '  time steps every: ',NTSTEP_BETWEEN_FRAMES
+    endif
+  endif
+
+
+  ! output point and element information for 3D movies
+  if(MOVIE_VOLUME) then
+    ! the following has to be true for the the array dimensions of eps to match with those of xstore etc..
+    ! note that epsilondev and eps_trace_over_3 don't have the same dimensions.. could cause trouble
+    if (NSPEC_CRUST_MANTLE_STR_OR_ATT /= NSPEC_CRUST_MANTLE) &
+      stop 'NSPEC_CRUST_MANTLE_STRAINS_ATT /= NSPEC_CRUST_MANTLE'
+    if (NSPEC_CRUST_MANTLE_STRAIN_ONLY /= NSPEC_CRUST_MANTLE) &
+      stop 'NSPEC_CRUST_MANTLE_STRAIN_ONLY /= NSPEC_CRUST_MANTLE'
+
+    write(prname,'(a,i6.6,a)') trim(LOCAL_PATH)//'/'//'proc',myrank,'_'
+    call count_points_movie_volume(prname,ibool_crust_mantle, xstore_crust_mantle,ystore_crust_mantle, &
+                zstore_crust_mantle,MOVIE_TOP,MOVIE_BOTTOM,MOVIE_WEST,MOVIE_EAST,MOVIE_NORTH,MOVIE_SOUTH, &
+                MOVIE_COARSE,npoints_3dmovie,nspecel_3dmovie,num_ibool_3dmovie,mask_ibool,mask_3dmovie)
+
+
+    allocate(nu_3dmovie(3,3,npoints_3dmovie),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating nu for 3d movie')
+
+    call write_movie_volume_mesh(npoints_3dmovie,prname,ibool_crust_mantle,xstore_crust_mantle, &
+                           ystore_crust_mantle,zstore_crust_mantle, muvstore_crust_mantle_3dmovie, &
+                           mask_3dmovie,mask_ibool,num_ibool_3dmovie,nu_3dmovie,MOVIE_COARSE)
+
+    if(myrank == 0) then
+      write(IMAIN,*)
+      write(IMAIN,*) 'Movie volume:'
+      write(IMAIN,*) '  Writing to movie3D*** files on local disk databases directory'
+      if(MOVIE_VOLUME_TYPE == 1) then
+        write(IMAIN,*) '  movie output: strain'
+      else if(MOVIE_VOLUME_TYPE == 2) then
+        write(IMAIN,*) '  movie output: time integral of strain'
+      else if(MOVIE_VOLUME_TYPE == 3) then
+        write(IMAIN,*) '  movie output: potency or integral of strain'
+      else if(MOVIE_VOLUME_TYPE == 4) then
+        write(IMAIN,*) '  movie output: divergence and curl'
+      else if(MOVIE_VOLUME_TYPE == 5) then
+        write(IMAIN,*) '  movie output: displacement'
+      else if(MOVIE_VOLUME_TYPE == 6) then
+        write(IMAIN,*) '  movie output: velocity'
+      endif
+      write(IMAIN,*) '  depth(T,B):',MOVIE_TOP,MOVIE_BOTTOM
+      write(IMAIN,*) '  lon(W,E)  :',MOVIE_WEST,MOVIE_EAST
+      write(IMAIN,*) '  lat(S,N)  :',MOVIE_SOUTH,MOVIE_NORTH
+      write(IMAIN,*) '  Starting at time step:',MOVIE_START, 'ending at:',MOVIE_STOP,'every: ',NTSTEP_BETWEEN_FRAMES
+    endif
+
+    if( MOVIE_VOLUME_TYPE < 1 .or. MOVIE_VOLUME_TYPE > 6) &
+        call exit_MPI(myrank, 'MOVIE_VOLUME_TYPE has to be 1,2,3,4,5 or 6')
+
+  endif ! MOVIE_VOLUME
+
+  ! sets up time increments and rotation constants
+  call prepare_timerun_constants(myrank,NSTEP, &
+                    DT,t0,scale_t,scale_t_inv,scale_displ,scale_veloc, &
+                    deltat,deltatover2,deltatsqover2, &
+                    b_deltat,b_deltatover2,b_deltatsqover2, &
+                    two_omega_earth,A_array_rotation,B_array_rotation, &
+                    b_two_omega_earth, SIMULATION_TYPE)
+
+  ! precomputes gravity factors
+  call prepare_timerun_gravity(myrank, &
+                    minus_g_cmb,minus_g_icb, &
+                    minus_gravity_table,minus_deriv_gravity_table, &
+                    density_table,d_ln_density_dr_table,minus_rho_g_over_kappa_fluid, &
+                    ONE_CRUST,RICB,RCMB,RTOPDDOUBLEPRIME, &
+                    R600,R670,R220,R771,R400,R80,RMOHO,RMIDDLE_CRUST,ROCEAN)
+
+  ! precomputes attenuation factors
+  if(ATTENUATION_VAL) then
+    call prepare_timerun_attenuation(myrank, &
+                factor_scale_crust_mantle,one_minus_sum_beta_crust_mantle,factor_common_crust_mantle, &
+                factor_scale_inner_core,one_minus_sum_beta_inner_core,factor_common_inner_core, &
+                c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+                c22store_crust_mantle,c23store_crust_mantle, &
+                c33store_crust_mantle,c44store_crust_mantle, &
+                c55store_crust_mantle,c66store_crust_mantle, &
+                muvstore_crust_mantle,muhstore_crust_mantle,ispec_is_tiso_crust_mantle, &
+                muvstore_inner_core, &
+                SIMULATION_TYPE,MOVIE_VOLUME,muvstore_crust_mantle_3dmovie, &
+                c11store_inner_core,c12store_inner_core,c13store_inner_core, &
+                c33store_inner_core,c44store_inner_core, &
+                alphaval,betaval,gammaval,b_alphaval,b_betaval,b_gammaval, &
+                deltat,b_deltat,LOCAL_PATH)
+  endif
+
+  if(myrank == 0) then
+
+  write(IMAIN,*) 'for overlapping of communications with calculations:'
+  write(IMAIN,*)
+
+  percentage_edge = 100.*count(is_on_a_slice_edge_crust_mantle(:))/real(NSPEC_CRUST_MANTLE)
+  write(IMAIN,*) 'percentage of edge elements in crust/mantle ',percentage_edge,'%'
+  write(IMAIN,*) 'percentage of volume elements in crust/mantle ',100. - percentage_edge,'%'
+  write(IMAIN,*)
+
+  percentage_edge = 100.*count(is_on_a_slice_edge_outer_core(:))/real(NSPEC_OUTER_CORE)
+  write(IMAIN,*) 'percentage of edge elements in outer core ',percentage_edge,'%'
+  write(IMAIN,*) 'percentage of volume elements in outer core ',100. - percentage_edge,'%'
+  write(IMAIN,*)
+
+  percentage_edge = 100.*count(is_on_a_slice_edge_inner_core(:))/real(NSPEC_INNER_CORE)
+  write(IMAIN,*) 'percentage of edge elements in inner core ',percentage_edge,'%'
+  write(IMAIN,*) 'percentage of volume elements in inner core ',100. - percentage_edge,'%'
+  write(IMAIN,*)
+
+  endif
+
+  if(.not. USE_NONBLOCKING_COMMS) then
+    is_on_a_slice_edge_crust_mantle(:) = .true.
+    is_on_a_slice_edge_outer_core(:) = .true.
+    is_on_a_slice_edge_inner_core(:) = .true.
+  endif
+
+  ! initialize arrays to zero
+  displ_crust_mantle(:,:) = 0._CUSTOM_REAL
+  veloc_crust_mantle(:,:) = 0._CUSTOM_REAL
+  accel_crust_mantle(:,:) = 0._CUSTOM_REAL
+
+  displ_outer_core(:) = 0._CUSTOM_REAL
+  veloc_outer_core(:) = 0._CUSTOM_REAL
+  accel_outer_core(:) = 0._CUSTOM_REAL
+
+  displ_inner_core(:,:) = 0._CUSTOM_REAL
+  veloc_inner_core(:,:) = 0._CUSTOM_REAL
+  accel_inner_core(:,:) = 0._CUSTOM_REAL
+
+  ! put negligible initial value to avoid very slow underflow trapping
+  if(FIX_UNDERFLOW_PROBLEM) then
+    displ_crust_mantle(:,:) = VERYSMALLVAL
+    displ_outer_core(:) = VERYSMALLVAL
+    displ_inner_core(:,:) = VERYSMALLVAL
+  endif
+
+  if (SIMULATION_TYPE == 3) then
+    rho_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
+    beta_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
+    alpha_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
+    if (NOISE_TOMOGRAPHY == 3) Sigma_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
+
+    ! approximate hessian
+    if( APPROXIMATE_HESS_KL ) then
+      allocate( hess_kl_crust_mantle(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT),stat=ier)
+      if( ier /= 0 ) call exit_MPI(myrank,'error allocating hessian')
+      hess_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
+    endif
+
+    ! For anisotropic kernels (in crust_mantle only)
+    cijkl_kl_crust_mantle(:,:,:,:,:) = 0._CUSTOM_REAL
+
+    rho_kl_outer_core(:,:,:,:) = 0._CUSTOM_REAL
+    alpha_kl_outer_core(:,:,:,:) = 0._CUSTOM_REAL
+
+    rho_kl_inner_core(:,:,:,:) = 0._CUSTOM_REAL
+    beta_kl_inner_core(:,:,:,:) = 0._CUSTOM_REAL
+    alpha_kl_inner_core(:,:,:,:) = 0._CUSTOM_REAL
+
+    div_displ_outer_core(:,:,:,:) = 0._CUSTOM_REAL
+    b_div_displ_outer_core(:,:,:,:) = 0._CUSTOM_REAL
+
+    ! deviatoric kernel check
+    if( deviatoric_outercore) then
+      nspec_beta_kl_outer_core = NSPEC_OUTER_CORE_ADJOINT
+    else
+      nspec_beta_kl_outer_core = 1
+    endif
+    allocate(beta_kl_outer_core(NGLLX,NGLLY,NGLLZ,nspec_beta_kl_outer_core),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating beta outercore')
+    beta_kl_outer_core(:,:,:,:) = 0._CUSTOM_REAL
+  endif
+
+  ! initialize to be on the save side for adjoint runs SIMULATION_TYPE==2
+  eps_trace_over_3_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
+  epsilondev_crust_mantle(:,:,:,:,:) = 0._CUSTOM_REAL
+  eps_trace_over_3_inner_core(:,:,:,:) = 0._CUSTOM_REAL
+  epsilondev_inner_core(:,:,:,:,:) = 0._CUSTOM_REAL
+  if(FIX_UNDERFLOW_PROBLEM) then
+    eps_trace_over_3_crust_mantle(:,:,:,:) = VERYSMALLVAL
+    epsilondev_crust_mantle(:,:,:,:,:) = VERYSMALLVAL
+    eps_trace_over_3_inner_core(:,:,:,:) = VERYSMALLVAL
+    epsilondev_inner_core(:,:,:,:,:) = VERYSMALLVAL
+  endif
+
+  if (COMPUTE_AND_STORE_STRAIN) then
+    if(MOVIE_VOLUME .and. (MOVIE_VOLUME_TYPE == 2 .or. MOVIE_VOLUME_TYPE == 3)) then
+      Iepsilondev_crust_mantle(:,:,:,:,:) = 0._CUSTOM_REAL
+      Ieps_trace_over_3_crust_mantle(:,:,:,:)=0._CUSTOM_REAL
+    endif
+  endif
+
+  ! clear memory variables if attenuation
+  if(ATTENUATION_VAL) then
+    R_memory_crust_mantle(:,:,:,:,:,:) = 0._CUSTOM_REAL
+    R_memory_inner_core(:,:,:,:,:,:) = 0._CUSTOM_REAL
+    if(FIX_UNDERFLOW_PROBLEM) then
+      R_memory_crust_mantle(:,:,:,:,:,:) = VERYSMALLVAL
+      R_memory_inner_core(:,:,:,:,:,:) = VERYSMALLVAL
+    endif
+  endif
+
+  ! reads files back from local disk or MT tape system if restart file
+  ! note: for SIMULATION_TYPE 3 simulations, the stored wavefields
+  !          will be read in the time loop after the Newmark time scheme update.
+  !          this makes indexing and timing easier to match with adjoint wavefields indexing.
+  call read_forward_arrays_startrun(myrank,NSTEP, &
+                    SIMULATION_TYPE,NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN, &
+                    it_begin,it_end, &
+                    displ_crust_mantle,veloc_crust_mantle,accel_crust_mantle, &
+                    displ_inner_core,veloc_inner_core,accel_inner_core, &
+                    displ_outer_core,veloc_outer_core,accel_outer_core, &
+                    R_memory_crust_mantle,R_memory_inner_core, &
+                    epsilondev_crust_mantle,epsilondev_inner_core, &
+                    A_array_rotation,B_array_rotation, &
+                    b_displ_crust_mantle,b_veloc_crust_mantle,b_accel_crust_mantle, &
+                    b_displ_inner_core,b_veloc_inner_core,b_accel_inner_core, &
+                    b_displ_outer_core,b_veloc_outer_core,b_accel_outer_core, &
+                    b_R_memory_crust_mantle,b_R_memory_inner_core, &
+                    b_epsilondev_crust_mantle,b_epsilondev_inner_core, &
+                    b_A_array_rotation,b_B_array_rotation,LOCAL_PATH)
+
+!<YANGL
+  ! NOISE TOMOGRAPHY
+  if ( NOISE_TOMOGRAPHY /= 0 ) then
+    allocate(noise_sourcearray(NDIM,NGLLX,NGLLY,NGLLZ,NSTEP), &
+            normal_x_noise(nmovie_points), &
+            normal_y_noise(nmovie_points), &
+            normal_z_noise(nmovie_points), &
+            mask_noise(nmovie_points), &
+            noise_surface_movie(NDIM,NGLLX,NGLLY,NSPEC2D_TOP(IREGION_CRUST_MANTLE)),stat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error allocating noise arrays')
+
+    noise_sourcearray(:,:,:,:,:) = 0._CUSTOM_REAL
+    normal_x_noise(:)            = 0._CUSTOM_REAL
+    normal_y_noise(:)            = 0._CUSTOM_REAL
+    normal_z_noise(:)            = 0._CUSTOM_REAL
+    mask_noise(:)                = 0._CUSTOM_REAL
+    noise_surface_movie(:,:,:,:) = 0._CUSTOM_REAL
+
+    call read_parameters_noise(myrank,nrec,NSTEP,nmovie_points, &
+                              islice_selected_rec,xi_receiver,eta_receiver,gamma_receiver,nu, &
+                              noise_sourcearray,xigll,yigll,zigll,NSPEC2D_TOP(IREGION_CRUST_MANTLE), &
+                              NIT, ibool_crust_mantle, ibelm_top_crust_mantle, &
+                              xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+                              irec_master_noise,normal_x_noise,normal_y_noise,normal_z_noise,mask_noise)
+
+    call check_parameters_noise(myrank,NOISE_TOMOGRAPHY,SIMULATION_TYPE,SAVE_FORWARD, &
+                              NUMBER_OF_RUNS, NUMBER_OF_THIS_RUN,ROTATE_SEISMOGRAMS_RT, &
+                              SAVE_ALL_SEISMOS_IN_ONE_FILE, USE_BINARY_FOR_LARGE_FILE, &
+                              MOVIE_COARSE,LOCAL_PATH,NSPEC2D_TOP(IREGION_CRUST_MANTLE),NSTEP)
+  endif
+!>YANGL
+
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+
+!
+!   s t a r t   t i m e   i t e r a t i o n s
+!
+
+! synchronize all processes to make sure everybody is ready to start time loop
+  call MPI_BARRIER(MPI_COMM_WORLD,ier)
+  if(myrank == 0) write(IMAIN,*) 'All processes are synchronized before time loop'
+
+  if(myrank == 0) then
+    write(IMAIN,*)
+    write(IMAIN,*) 'Starting time iteration loop...'
+    write(IMAIN,*)
+  endif
+
+! create an empty file to monitor the start of the simulation
+  if(myrank == 0) then
+    open(unit=IOUT,file=trim(OUTPUT_FILES)//'/starttimeloop.txt',status='unknown',action='write')
+    write(IOUT,*) 'hello, starting time loop'
+    close(IOUT)
+  endif
+
+! initialize variables for writing seismograms
+  seismo_offset = it_begin-1
+  seismo_current = 0
+
+#ifdef _HANDOPT
+  imodulo_NGLOB_CRUST_MANTLE = mod(NGLOB_CRUST_MANTLE,3)
+  imodulo_NGLOB_CRUST_MANTLE4 = mod(NGLOB_CRUST_MANTLE,4)
+  imodulo_NGLOB_INNER_CORE = mod(NGLOB_INNER_CORE,3)
+#endif
+
+! get MPI starting time
+  time_start = MPI_WTIME()
+
+! *********************************************************
+! ************* MAIN LOOP OVER THE TIME STEPS *************
+! *********************************************************
+
+  do it = it_begin,it_end
+
+    ! update position in seismograms
+    seismo_current = seismo_current + 1
+
+    ! Newark time scheme update    
+#ifdef _HANDOPT
+! way 2:
+! One common technique in computational science to help enhance pipelining is loop unrolling
+!
+! we're accessing NDIM=3 components at each line,
+! that is, for an iteration, the register must contain
+! NDIM * displ_ + NDIM * veloc_ + NDIM * accel + deltat + deltatsq..
+! in most cases a real (CUSTOM_REAL) value will have 4 bytes,
+! assuming a default cache size of about 128 bytes, we unroll here in steps of 3, thus 29 reals or 118 bytes,
+! rather than with steps of 4
+    ! mantle
+    if(imodulo_NGLOB_CRUST_MANTLE >= 1) then
+      do i = 1,imodulo_NGLOB_CRUST_MANTLE
+        displ_crust_mantle(:,i) = displ_crust_mantle(:,i) &
+          + deltat*veloc_crust_mantle(:,i) + deltatsqover2*accel_crust_mantle(:,i)
+
+        veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) &
+          + deltatover2*accel_crust_mantle(:,i)
+
+        accel_crust_mantle(:,i) = 0._CUSTOM_REAL
+      enddo
+    endif
+    do i = imodulo_NGLOB_CRUST_MANTLE+1,NGLOB_CRUST_MANTLE, 3 ! in steps of 3
+      displ_crust_mantle(:,i) = displ_crust_mantle(:,i) &
+        + deltat*veloc_crust_mantle(:,i) + deltatsqover2*accel_crust_mantle(:,i)
+      displ_crust_mantle(:,i+1) = displ_crust_mantle(:,i+1) &
+        + deltat*veloc_crust_mantle(:,i+1) + deltatsqover2*accel_crust_mantle(:,i+1)
+      displ_crust_mantle(:,i+2) = displ_crust_mantle(:,i+2) &
+        + deltat*veloc_crust_mantle(:,i+2) + deltatsqover2*accel_crust_mantle(:,i+2)
+
+
+      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) &
+        + deltatover2*accel_crust_mantle(:,i)
+      veloc_crust_mantle(:,i+1) = veloc_crust_mantle(:,i+1) &
+        + deltatover2*accel_crust_mantle(:,i+1)
+      veloc_crust_mantle(:,i+2) = veloc_crust_mantle(:,i+2) &
+        + deltatover2*accel_crust_mantle(:,i+2)
+
+      ! set acceleration to zero
+      ! note: we do initialize acceleration in this loop since it is read already into the cache,
+      !           otherwise it would have to be read in again for this explicitly,
+      !           which would make this step more expensive
+      accel_crust_mantle(:,i) = 0._CUSTOM_REAL
+      accel_crust_mantle(:,i+1) = 0._CUSTOM_REAL
+      accel_crust_mantle(:,i+2) = 0._CUSTOM_REAL
+    enddo
+
+    ! outer core 
+    do i=1,NGLOB_OUTER_CORE
+      displ_outer_core(i) = displ_outer_core(i) &
+        + deltat*veloc_outer_core(i) + deltatsqover2*accel_outer_core(i)
+
+      veloc_outer_core(i) = veloc_outer_core(i) &
+        + deltatover2*accel_outer_core(i)
+
+      accel_outer_core(i) = 0._CUSTOM_REAL
+    enddo
+
+    ! inner core
+    if(imodulo_NGLOB_INNER_CORE >= 1) then
+      do i = 1,imodulo_NGLOB_INNER_CORE
+        displ_inner_core(:,i) = displ_inner_core(:,i) &
+          + deltat*veloc_inner_core(:,i) + deltatsqover2*accel_inner_core(:,i)
+
+        veloc_inner_core(:,i) = veloc_inner_core(:,i) &
+          + deltatover2*accel_inner_core(:,i)
+
+        accel_inner_core(:,i) = 0._CUSTOM_REAL
+      enddo
+    endif
+    do i = imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE, 3 ! in steps of 3
+      displ_inner_core(:,i) = displ_inner_core(:,i) &
+        + deltat*veloc_inner_core(:,i) + deltatsqover2*accel_inner_core(:,i)
+      displ_inner_core(:,i+1) = displ_inner_core(:,i+1) &
+        + deltat*veloc_inner_core(:,i+1) + deltatsqover2*accel_inner_core(:,i+1)
+      displ_inner_core(:,i+2) = displ_inner_core(:,i+2) &
+        + deltat*veloc_inner_core(:,i+2) + deltatsqover2*accel_inner_core(:,i+2)
+
+
+      veloc_inner_core(:,i) = veloc_inner_core(:,i) &
+        + deltatover2*accel_inner_core(:,i)
+      veloc_inner_core(:,i+1) = veloc_inner_core(:,i+1) &
+        + deltatover2*accel_inner_core(:,i+1)
+      veloc_inner_core(:,i+2) = veloc_inner_core(:,i+2) &
+        + deltatover2*accel_inner_core(:,i+2)
+
+      accel_inner_core(:,i) = 0._CUSTOM_REAL
+      accel_inner_core(:,i+1) = 0._CUSTOM_REAL
+      accel_inner_core(:,i+2) = 0._CUSTOM_REAL
+    enddo    
+    
+#else
+! way 1:
+    ! mantle
+    do i=1,NGLOB_CRUST_MANTLE
+      displ_crust_mantle(:,i) = displ_crust_mantle(:,i) &
+        + deltat*veloc_crust_mantle(:,i) + deltatsqover2*accel_crust_mantle(:,i)
+      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) &
+        + deltatover2*accel_crust_mantle(:,i)
+      accel_crust_mantle(:,i) = 0._CUSTOM_REAL
+    enddo
+    ! outer core
+    do i=1,NGLOB_OUTER_CORE
+      displ_outer_core(i) = displ_outer_core(i) &
+        + deltat*veloc_outer_core(i) + deltatsqover2*accel_outer_core(i)
+      veloc_outer_core(i) = veloc_outer_core(i) &
+        + deltatover2*accel_outer_core(i)
+      accel_outer_core(i) = 0._CUSTOM_REAL
+    enddo
+    ! inner core
+    do i=1,NGLOB_INNER_CORE
+      displ_inner_core(:,i) = displ_inner_core(:,i) &
+        + deltat*veloc_inner_core(:,i) + deltatsqover2*accel_inner_core(:,i)
+      veloc_inner_core(:,i) = veloc_inner_core(:,i) &
+        + deltatover2*accel_inner_core(:,i)
+      accel_inner_core(:,i) = 0._CUSTOM_REAL
+    enddo
+#endif
+
+
+
+
+    ! backward field
+    if (SIMULATION_TYPE == 3) then
+
+#ifdef _HANDOPT
+! way 2:
+      ! mantle
+      if(imodulo_NGLOB_CRUST_MANTLE >= 1) then
+        do i=1,imodulo_NGLOB_CRUST_MANTLE
+          b_displ_crust_mantle(:,i) = b_displ_crust_mantle(:,i) &
+            + b_deltat*b_veloc_crust_mantle(:,i) + b_deltatsqover2*b_accel_crust_mantle(:,i)
+          b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) &
+            + b_deltatover2*b_accel_crust_mantle(:,i)
+          b_accel_crust_mantle(:,i) = 0._CUSTOM_REAL
+        enddo
+      endif
+      do i=imodulo_NGLOB_CRUST_MANTLE+1,NGLOB_CRUST_MANTLE,3
+        b_displ_crust_mantle(:,i) = b_displ_crust_mantle(:,i) &
+          + b_deltat*b_veloc_crust_mantle(:,i) + b_deltatsqover2*b_accel_crust_mantle(:,i)
+        b_displ_crust_mantle(:,i+1) = b_displ_crust_mantle(:,i+1) &
+          + b_deltat*b_veloc_crust_mantle(:,i+1) + b_deltatsqover2*b_accel_crust_mantle(:,i+1)
+        b_displ_crust_mantle(:,i+2) = b_displ_crust_mantle(:,i+2) &
+          + b_deltat*b_veloc_crust_mantle(:,i+2) + b_deltatsqover2*b_accel_crust_mantle(:,i+2)
+
+
+        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) &
+          + b_deltatover2*b_accel_crust_mantle(:,i)
+        b_veloc_crust_mantle(:,i+1) = b_veloc_crust_mantle(:,i+1) &
+          + b_deltatover2*b_accel_crust_mantle(:,i+1)
+        b_veloc_crust_mantle(:,i+2) = b_veloc_crust_mantle(:,i+2) &
+          + b_deltatover2*b_accel_crust_mantle(:,i+2)
+
+        b_accel_crust_mantle(:,i) = 0._CUSTOM_REAL
+        b_accel_crust_mantle(:,i+1) = 0._CUSTOM_REAL
+        b_accel_crust_mantle(:,i+2) = 0._CUSTOM_REAL
+      enddo
+
+      ! outer core
+      do i=1,NGLOB_OUTER_CORE
+        b_displ_outer_core(i) = b_displ_outer_core(i) &
+          + b_deltat*b_veloc_outer_core(i) + b_deltatsqover2*b_accel_outer_core(i)
+        b_veloc_outer_core(i) = b_veloc_outer_core(i) &
+          + b_deltatover2*b_accel_outer_core(i)
+        b_accel_outer_core(i) = 0._CUSTOM_REAL
+      enddo
+
+      ! inner core  
+      if(imodulo_NGLOB_INNER_CORE >= 1) then
+        do i=1,imodulo_NGLOB_INNER_CORE
+          b_displ_inner_core(:,i) = b_displ_inner_core(:,i) &
+            + b_deltat*b_veloc_inner_core(:,i) + b_deltatsqover2*b_accel_inner_core(:,i)
+          b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) &
+            + b_deltatover2*b_accel_inner_core(:,i)
+          b_accel_inner_core(:,i) = 0._CUSTOM_REAL
+        enddo
+      endif
+      do i=imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE,3
+        b_displ_inner_core(:,i) = b_displ_inner_core(:,i) &
+          + b_deltat*b_veloc_inner_core(:,i) + b_deltatsqover2*b_accel_inner_core(:,i)
+        b_displ_inner_core(:,i+1) = b_displ_inner_core(:,i+1) &
+          + b_deltat*b_veloc_inner_core(:,i+1) + b_deltatsqover2*b_accel_inner_core(:,i+1)
+        b_displ_inner_core(:,i+2) = b_displ_inner_core(:,i+2) &
+          + b_deltat*b_veloc_inner_core(:,i+2) + b_deltatsqover2*b_accel_inner_core(:,i+2)
+
+        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) &
+          + b_deltatover2*b_accel_inner_core(:,i)
+        b_veloc_inner_core(:,i+1) = b_veloc_inner_core(:,i+1) &
+          + b_deltatover2*b_accel_inner_core(:,i+1)
+        b_veloc_inner_core(:,i+2) = b_veloc_inner_core(:,i+2) &
+          + b_deltatover2*b_accel_inner_core(:,i+2)
+
+        b_accel_inner_core(:,i) = 0._CUSTOM_REAL
+        b_accel_inner_core(:,i+1) = 0._CUSTOM_REAL
+        b_accel_inner_core(:,i+2) = 0._CUSTOM_REAL
+      enddo
+#else    
+! way 1:
+      ! mantle
+      do i=1,NGLOB_CRUST_MANTLE
+        b_displ_crust_mantle(:,i) = b_displ_crust_mantle(:,i) &
+          + b_deltat*b_veloc_crust_mantle(:,i) + b_deltatsqover2*b_accel_crust_mantle(:,i)
+        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) &
+          + b_deltatover2*b_accel_crust_mantle(:,i)
+        b_accel_crust_mantle(:,i) = 0._CUSTOM_REAL
+      enddo
+      ! outer core
+      do i=1,NGLOB_OUTER_CORE
+        b_displ_outer_core(i) = b_displ_outer_core(i) &
+          + b_deltat*b_veloc_outer_core(i) + b_deltatsqover2*b_accel_outer_core(i)
+        b_veloc_outer_core(i) = b_veloc_outer_core(i) &
+          + b_deltatover2*b_accel_outer_core(i)
+        b_accel_outer_core(i) = 0._CUSTOM_REAL
+      enddo
+      ! inner core
+      do i=1,NGLOB_INNER_CORE
+        b_displ_inner_core(:,i) = b_displ_inner_core(:,i) &
+          + b_deltat*b_veloc_inner_core(:,i) + b_deltatsqover2*b_accel_inner_core(:,i)
+        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) &
+          + b_deltatover2*b_accel_inner_core(:,i)
+        b_accel_inner_core(:,i) = 0._CUSTOM_REAL
+      enddo
+#endif
+    endif ! SIMULATION_TYPE == 3
+
+    ! integral of strain for adjoint movie volume
+    if(MOVIE_VOLUME .and. (MOVIE_VOLUME_TYPE == 2 .or. MOVIE_VOLUME_TYPE == 3) ) then
+      Iepsilondev_crust_mantle(:,:,:,:,:) = Iepsilondev_crust_mantle(:,:,:,:,:)  &
+                                              + deltat*epsilondev_crust_mantle(:,:,:,:,:)
+      Ieps_trace_over_3_crust_mantle(:,:,:,:) = Ieps_trace_over_3_crust_mantle(:,:,:,:) &
+                                              + deltat*eps_trace_over_3_crust_mantle(:,:,:,:)
+    endif
+
+    ! daniel: debugging
+    !if( maxval(displ_crust_mantle(1,:)**2 + &
+    !                displ_crust_mantle(2,:)**2 + displ_crust_mantle(3,:)**2) > 1.e4 ) then
+    !  print*,'slice',myrank
+    !  print*,'  crust_mantle displ:', maxval(displ_crust_mantle(1,:)), &
+    !           maxval(displ_crust_mantle(2,:)),maxval(displ_crust_mantle(3,:))
+    !  print*,'  indxs: ',maxloc( displ_crust_mantle(1,:)),maxloc( displ_crust_mantle(2,:)),maxloc( displ_crust_mantle(3,:))
+    !  indx = maxloc( displ_crust_mantle(3,:) )
+    !  rval = xstore_crust_mantle(indx(1))
+    !  thetaval = ystore_crust_mantle(indx(1))
+    !  phival = zstore_crust_mantle(indx(1))
+    !  !thetaval = PI/2.0d0-datan(1.006760466d0*dcos(dble(thetaval))/dmax1(TINYVAL,dsin(dble(thetaval))))
+    !  print*,'r/lat/lon:',rval*R_EARTH_KM,90.0-thetaval*180./PI,phival*180./PI
+    !  call rthetaphi_2_xyz(rval,thetaval,phival,xstore_crust_mantle(indx(1)),&
+    !                     ystore_crust_mantle(indx(1)),zstore_crust_mantle(indx(1)))
+    !  print*,'x/y/z:',rval,thetaval,phival
+    !  call exit_MPI(myrank,'error stability')
+    !endif
+
+
+    ! compute the maximum of the norm of the displacement
+    ! in all the slices using an MPI reduction
+    ! and output timestamp file to check that simulation is running fine
+    if(mod(it,NTSTEP_BETWEEN_OUTPUT_INFO) == 0 .or. it == 5 .or. it == NSTEP) &
+      call check_simulation_stability(it,displ_crust_mantle,displ_inner_core,displ_outer_core, &
+                          b_displ_crust_mantle,b_displ_inner_core,b_displ_outer_core, &
+                          eps_trace_over_3_crust_mantle,epsilondev_crust_mantle, &
+                          SIMULATION_TYPE,OUTPUT_FILES,time_start,DT,t0,NSTEP, &
+                          myrank)
+
+
+    ! ****************************************************
+    !   big loop over all spectral elements in the fluid
+    ! ****************************************************
+
+    ! compute internal forces in the fluid region
+    if(CUSTOM_REAL == SIZE_REAL) then
+      time = sngl((dble(it-1)*DT-t0)*scale_t_inv)
+    else
+      time = (dble(it-1)*DT-t0)*scale_t_inv
+    endif
+
+    iphase = 0 ! do not start any non blocking communications at this stage
+    icall = 1  ! compute all the outer elements first in the case of non blocking MPI
+
+    if( USE_DEVILLE_PRODUCTS_VAL ) then
+      ! uses Deville et al. (2002) routine
+      call compute_forces_outer_core_Dev(time,deltat,two_omega_earth, &
+           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid, &
+           displ_outer_core,accel_outer_core,div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
+           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+    else
+      ! div_displ_outer_core is initialized to zero in the following subroutine.
+      call compute_forces_outer_core(time,deltat,two_omega_earth, &
+           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid, &
+           displ_outer_core,accel_outer_core,div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
+           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+    endif
+
+    if (SIMULATION_TYPE == 3) then
+      ! note on backward/reconstructed wavefields:
+      !       time for b_displ( it=1 ) corresponds to (NSTEP - 1)*DT - t0  (after Newmark scheme...)
+      !       as we start with saved wavefields b_displ( 1 ) <-> displ( NSTEP ) which correspond
+      !       to a time (NSTEP - (it-1) - 1)*DT - t0
+      !       for reconstructing the rotational contributions
+      if(CUSTOM_REAL == SIZE_REAL) then
+        time = sngl((dble(NSTEP-it)*DT-t0)*scale_t_inv)
+      else
+        time = (dble(NSTEP-it)*DT-t0)*scale_t_inv
+      endif
+
+      b_iphase = 0 ! do not start any non blocking communications at this stage
+      b_icall = 1  ! compute all the outer elements first in the case of non blocking MPI
+
+      if( USE_DEVILLE_PRODUCTS_VAL ) then
+        ! uses Deville et al. (2002) routine
+        call compute_forces_outer_core_Dev(time,b_deltat,b_two_omega_earth, &
+           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid, &
+           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
+           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+      else
+        call compute_forces_outer_core(time,b_deltat,b_two_omega_earth, &
+           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid, &
+           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
+           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+      endif
+    endif
+
+    ! Stacey absorbing boundaries
+    if(NCHUNKS_VAL /= 6 .and. ABSORBING_CONDITIONS) then
+      call compute_stacey_outer_core(ichunk,SIMULATION_TYPE,SAVE_FORWARD, &
+                              NSTEP,it,ibool_outer_core, &
+                              veloc_outer_core,accel_outer_core,b_accel_outer_core, &
+                              vp_outer_core,wgllwgll_xz,wgllwgll_yz,wgllwgll_xy, &
+                              jacobian2D_bottom_outer_core, &
+                              jacobian2D_xmin_outer_core,jacobian2D_xmax_outer_core, &
+                              jacobian2D_ymin_outer_core,jacobian2D_ymax_outer_core, &
+                              ibelm_bottom_outer_core, &
+                              ibelm_xmin_outer_core,ibelm_xmax_outer_core, &
+                              ibelm_ymin_outer_core,ibelm_ymax_outer_core, &
+                              nimin_outer_core,nimax_outer_core, &
+                              njmin_outer_core,njmax_outer_core, &
+                              nkmin_xi_outer_core,nkmin_eta_outer_core, &
+                              NSPEC2D_BOTTOM, &
+                              nspec2D_xmin_outer_core,nspec2D_xmax_outer_core, &
+                              nspec2D_ymin_outer_core,nspec2D_ymax_outer_core, &
+                              reclen_zmin, &
+                              reclen_xmin_outer_core,reclen_xmax_outer_core, &
+                              reclen_ymin_outer_core,reclen_ymax_outer_core, &
+                              nabs_zmin_oc, &
+                              nabs_xmin_oc,nabs_xmax_oc,nabs_ymin_oc,nabs_ymax_oc, &
+                              absorb_zmin_outer_core, &
+                              absorb_xmin_outer_core,absorb_xmax_outer_core, &
+                              absorb_ymin_outer_core,absorb_ymax_outer_core)
+    endif ! Stacey conditions
+
+
+    ! ****************************************************
+    ! **********  add matching with solid part  **********
+    ! ****************************************************
+
+    ! only for elements in first matching layer in the fluid
+
+    !---
+    !--- couple with mantle at the top of the outer core
+    !---
+    if(ACTUALLY_COUPLE_FLUID_CMB) &
+      call compute_coupling_fluid_CMB(displ_crust_mantle,b_displ_crust_mantle, &
+                            ibool_crust_mantle,ibelm_bottom_crust_mantle,  &
+                            accel_outer_core,b_accel_outer_core, &
+                            normal_top_outer_core,jacobian2D_top_outer_core, &
+                            wgllwgll_xy,ibool_outer_core,ibelm_top_outer_core, &
+                            SIMULATION_TYPE,NSPEC2D_TOP(IREGION_OUTER_CORE))
+
+    !---
+    !--- couple with inner core at the bottom of the outer core
+    !---
+    if(ACTUALLY_COUPLE_FLUID_ICB) &
+      call compute_coupling_fluid_ICB(displ_inner_core,b_displ_inner_core, &
+                            ibool_inner_core,ibelm_top_inner_core,  &
+                            accel_outer_core,b_accel_outer_core, &
+                            normal_bottom_outer_core,jacobian2D_bottom_outer_core, &
+                            wgllwgll_xy,ibool_outer_core,ibelm_bottom_outer_core, &
+                            SIMULATION_TYPE,NSPEC2D_BOTTOM(IREGION_OUTER_CORE))
+
+
+    ! assemble all the contributions between slices using MPI
+
+    ! outer core
+    if(USE_NONBLOCKING_COMMS) then
+      iphase = 1 ! start the non blocking communications
+      call assemble_MPI_scalar(myrank,accel_outer_core,NGLOB_OUTER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+            iboolfaces_outer_core,iboolcorner_outer_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL,iphase)
+
+      icall = 2 ! now compute all the inner elements in the case of non blocking MPI
+
+      if( USE_DEVILLE_PRODUCTS_VAL ) then
+        ! uses Deville et al. (2002) routine
+        call compute_forces_outer_core_Dev(time,deltat,two_omega_earth, &
+           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid,displ_outer_core,accel_outer_core,div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
+           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+      else
+        ! div_displ_outer_core is initialized to zero in the following subroutine.
+        call compute_forces_outer_core(time,deltat,two_omega_earth, &
+           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid,displ_outer_core,accel_outer_core,div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
+           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+      endif
+
+      do while (iphase <= 7) ! make sure the last communications are finished and processed
+        call assemble_MPI_scalar(myrank,accel_outer_core,NGLOB_OUTER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+            iboolfaces_outer_core,iboolcorner_outer_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL,iphase)
+      enddo
+
+    else ! if(.not. USE_NONBLOCKING_COMMS) then
+
+      call assemble_MPI_scalar_block(myrank,accel_outer_core,NGLOB_OUTER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_outer_core,iboolright_xi_outer_core, &
+            iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+            iboolfaces_outer_core,iboolcorner_outer_core, &
+            iprocfrom_faces,iprocto_faces,imsg_type, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
+            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL)
+
+    endif
+
+    ! multiply by the inverse of the mass matrix and update velocity
+    do i=1,NGLOB_OUTER_CORE
+      accel_outer_core(i) = accel_outer_core(i)*rmass_outer_core(i)
+      veloc_outer_core(i) = veloc_outer_core(i) + deltatover2*accel_outer_core(i)
+    enddo
+
+    if (SIMULATION_TYPE == 3) then
+
+! ------------------- new non blocking implementation -------------------
+
+    ! outer core
+      if(USE_NONBLOCKING_COMMS) then
+        b_iphase = 1 ! start the non blocking communications
+        call assemble_MPI_scalar(myrank,b_accel_outer_core,NGLOB_OUTER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+            iboolfaces_outer_core,iboolcorner_outer_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL,b_iphase)
+
+        b_icall = 2 ! now compute all the inner elements in the case of non blocking MPI
+
+        if( USE_DEVILLE_PRODUCTS_VAL ) then
+          ! uses Deville et al. (2002) routine
+          call compute_forces_outer_core_Dev(time,b_deltat,b_two_omega_earth, &
+           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid, &
+           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
+           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+        else
+          ! div_displ_outer_core is initialized to zero in the following subroutine.
+          call compute_forces_outer_core(time,b_deltat,b_two_omega_earth, &
+           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
+           minus_rho_g_over_kappa_fluid, &
+           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
+           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
+           xix_outer_core,xiy_outer_core,xiz_outer_core, &
+           etax_outer_core,etay_outer_core,etaz_outer_core, &
+           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+          is_on_a_slice_edge_outer_core, &
+          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+          iboolfaces_outer_core,iboolcorner_outer_core, &
+          iprocfrom_faces,iprocto_faces, &
+          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
+           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+           ibool_outer_core,MOVIE_VOLUME)
+        endif
+
+        do while (b_iphase <= 7) ! make sure the last communications are finished and processed
+          call assemble_MPI_scalar(myrank,b_accel_outer_core,NGLOB_OUTER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+            iboolfaces_outer_core,iboolcorner_outer_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL,b_iphase)
+        enddo
+
+      else ! if(.not. USE_NONBLOCKING_COMMS) then
+
+        call assemble_MPI_scalar_block(myrank,b_accel_outer_core,NGLOB_OUTER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_outer_core,iboolright_xi_outer_core, &
+            iboolleft_eta_outer_core,iboolright_eta_outer_core, &
+            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
+            iboolfaces_outer_core,iboolcorner_outer_core, &
+            iprocfrom_faces,iprocto_faces,imsg_type, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar, &
+            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL)
+
+      endif
+
+! ------------------- new non blocking implementation -------------------
+
+      ! Newmark time scheme - corrector for fluid parts
+      do i=1,NGLOB_OUTER_CORE
+        b_accel_outer_core(i) = b_accel_outer_core(i)*rmass_outer_core(i)
+        b_veloc_outer_core(i) = b_veloc_outer_core(i) + b_deltatover2*b_accel_outer_core(i)
+      enddo
+
+    endif
+
+    ! ****************************************************
+    !   big loop over all spectral elements in the solid
+    ! ****************************************************
+
+    ! compute internal forces in the solid regions
+
+    ! for anisotropy and gravity, x y and z contain r theta and phi
+
+    iphase = 0 ! do not start any non blocking communications at this stage
+    iphase_CC = 0 ! do not start any non blocking communications at this stage
+    icall = 1  ! compute all the outer elements first in the case of non blocking MPI
+
+    if( USE_DEVILLE_PRODUCTS_VAL ) then
+      call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_crust_mantle,accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,icall, &
+            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT, &
+          hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+      ! --idoubling_crust_mantle, &
+          R_memory_crust_mantle,epsilondev_crust_mantle, &
+          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          alphaval,betaval,gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+    else
+      call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_crust_mantle,accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,icall, &
+            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz, &
+          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+        ! --idoubling_crust_mantle, &
+          R_memory_crust_mantle,epsilondev_crust_mantle, &
+          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          alphaval,betaval,gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+    endif
+
+    if (SIMULATION_TYPE == 3 ) then
+
+      b_iphase = 0 ! do not start any non blocking communications at this stage
+      b_iphase_CC = 0 ! do not start any non blocking communications at this stage
+      b_icall = 1  ! compute all the outer elements first in the case of non blocking MPI
+
+    ! for anisotropy and gravity, x y and z contain r theta and phi
+      if( USE_DEVILLE_PRODUCTS_VAL ) then
+        call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_crust_mantle,b_accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,b_icall, &
+            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT, &
+          hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+     ! --     idoubling_crust_mantle, &
+          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
+          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+      else
+        call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_crust_mantle,b_accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,b_icall, &
+            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz, &
+          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+      ! --idoubling_crust_mantle, &
+          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
+          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+
+      endif
+    endif
+
+    ! Deville routine
+    if( USE_DEVILLE_PRODUCTS_VAL ) then
+      call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_inner_core,accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,icall, &
+            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          alphaval,betaval,gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+    else
+      call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_inner_core,accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,icall, &
+            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          alphaval,betaval,gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+    endif
+
+    if (SIMULATION_TYPE == 3) then
+      if( USE_DEVILLE_PRODUCTS_VAL ) then
+        call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_inner_core,b_accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,b_icall, &
+            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          b_alphaval,b_betaval,b_gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+      else
+        call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_inner_core,b_accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,b_icall, &
+            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          b_alphaval,b_betaval,b_gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+      endif
+    endif
+
+    ! Stacey
+    if(NCHUNKS_VAL /= 6 .and. ABSORBING_CONDITIONS) then
+      call compute_stacey_crust_mantle(ichunk,SIMULATION_TYPE, &
+                              NSTEP,it,SAVE_FORWARD,ibool_crust_mantle, &
+                              veloc_crust_mantle,accel_crust_mantle,b_accel_crust_mantle, &
+                              jacobian2D_xmin_crust_mantle,jacobian2D_xmax_crust_mantle, &
+                              jacobian2D_ymin_crust_mantle,jacobian2D_ymax_crust_mantle, &
+                              wgllwgll_xz,wgllwgll_yz, &
+                              normal_xmin_crust_mantle,normal_xmax_crust_mantle, &
+                              normal_ymin_crust_mantle,normal_ymax_crust_mantle, &
+                              rho_vp_crust_mantle,rho_vs_crust_mantle, &
+                              ibelm_xmin_crust_mantle,ibelm_xmax_crust_mantle, &
+                              ibelm_ymin_crust_mantle,ibelm_ymax_crust_mantle, &
+                              nimin_crust_mantle,nimax_crust_mantle, &
+                              njmin_crust_mantle,njmax_crust_mantle, &
+                              nkmin_xi_crust_mantle,nkmin_eta_crust_mantle, &
+                              nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle, &
+                              nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle, &
+                              reclen_xmin_crust_mantle,reclen_xmax_crust_mantle, &
+                              reclen_ymin_crust_mantle,reclen_ymax_crust_mantle, &
+                              nabs_xmin_cm,nabs_xmax_cm,nabs_ymin_cm,nabs_ymax_cm, &
+                              absorb_xmin_crust_mantle5,absorb_xmax_crust_mantle5, &
+                              absorb_ymin_crust_mantle5,absorb_ymax_crust_mantle5)
+    endif ! Stacey conditions
+
+    ! add the sources
+    if (SIMULATION_TYPE == 1) &
+      call compute_add_sources(myrank,NSOURCES, &
+                                accel_crust_mantle,sourcearrays, &
+                                DT,t0,tshift_cmt,hdur_gaussian,ibool_crust_mantle, &
+                                islice_selected_source,ispec_selected_source,it, &
+                                hdur,xi_source,eta_source,gamma_source,nu_source)
+
+    ! add adjoint sources
+    if (SIMULATION_TYPE == 2 .or. SIMULATION_TYPE == 3) then
+      if( nadj_rec_local > 0 ) &
+        call compute_add_sources_adjoint(myrank,nrec, &
+                                nadj_rec_local,NSTEP,NTSTEP_BETWEEN_READ_ADJSRC, &
+                                accel_crust_mantle,adj_sourcearrays, &
+                                nu,xi_receiver,eta_receiver,gamma_receiver, &
+                                xigll,yigll,zigll,ibool_crust_mantle, &
+                                islice_selected_rec,ispec_selected_rec, &
+                                NSTEP_SUB_ADJ,iadjsrc_len,iadjsrc,iadj_vec, &
+                                it,it_begin,station_name,network_name,DT)
+    endif
+
+    ! add sources for backward/reconstructed wavefield
+    if (SIMULATION_TYPE == 3) &
+      call compute_add_sources_backward(myrank,NSOURCES,NSTEP, &
+                                b_accel_crust_mantle,sourcearrays, &
+                                DT,t0,tshift_cmt,hdur_gaussian,ibool_crust_mantle, &
+                                islice_selected_source,ispec_selected_source,it, &
+                                hdur,xi_source,eta_source,gamma_source,nu_source)
+
+!<YANGL
+    ! NOISE_TOMOGRAPHY
+    if ( NOISE_TOMOGRAPHY == 1 ) then
+       ! the first step of noise tomography is to use |S(\omega)|^2 as a point force source at one of the receivers.
+       ! hence, instead of a moment tensor 'sourcearrays', a 'noise_sourcearray' for a point force is needed.
+       ! furthermore, the CMTSOLUTION needs to be zero, i.e., no earthquakes.
+       ! now this must be manually set in DATA/CMTSOLUTION, by USERS.
+       call add_source_master_rec_noise(myrank,nrec, &
+                                NSTEP,accel_crust_mantle,noise_sourcearray, &
+                                ibool_crust_mantle,islice_selected_rec,ispec_selected_rec, &
+                                it,irec_master_noise)
+    elseif ( NOISE_TOMOGRAPHY == 2 ) then
+       ! second step of noise tomography, i.e., read the surface movie saved at every timestep
+       ! use the movie to drive the ensemble forward wavefield
+       call noise_read_add_surface_movie(nmovie_points,accel_crust_mantle, &
+                              normal_x_noise,normal_y_noise,normal_z_noise,mask_noise, &
+                              ibelm_top_crust_mantle,ibool_crust_mantle, &
+                              NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie, &
+                              NSTEP-it+1,jacobian2D_top_crust_mantle,wgllwgll_xy)
+        ! be careful, since ensemble forward sources are reversals of generating wavefield "eta"
+        ! hence the "NSTEP-it+1", i.e., start reading from the last timestep
+        ! note the ensemble forward sources are generally distributed on the surface of the earth
+        ! that's to say, the ensemble forward source is kind of a surface force density, not a body force density
+        ! therefore, we must add it here, before applying the inverse of mass matrix
+    elseif ( NOISE_TOMOGRAPHY == 3 ) then
+        ! third step of noise tomography, i.e., read the surface movie saved at every timestep
+        ! use the movie to reconstruct the ensemble forward wavefield
+        ! the ensemble adjoint wavefield is done as usual
+        ! note instead of "NSTEP-it+1", now we us "it", since reconstruction is a reversal of reversal
+        call noise_read_add_surface_movie(nmovie_points,b_accel_crust_mantle, &
+                              normal_x_noise,normal_y_noise,normal_z_noise,mask_noise, &
+                              ibelm_top_crust_mantle,ibool_crust_mantle, &
+                              NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie, &
+                              it,jacobian2D_top_crust_mantle,wgllwgll_xy)
+    endif
+!>YANGL
+
+    ! ****************************************************
+    ! **********  add matching with fluid part  **********
+    ! ****************************************************
+
+    ! only for elements in first matching layer in the solid
+
+    !---
+    !--- couple with outer core at the bottom of the mantle
+    !---
+    if(ACTUALLY_COUPLE_FLUID_CMB) &
+      call compute_coupling_CMB_fluid(displ_crust_mantle,b_displ_crust_mantle, &
+                            accel_crust_mantle,b_accel_crust_mantle, &
+                            ibool_crust_mantle,ibelm_bottom_crust_mantle,  &
+                            accel_outer_core,b_accel_outer_core, &
+                            normal_top_outer_core,jacobian2D_top_outer_core, &
+                            wgllwgll_xy,ibool_outer_core,ibelm_top_outer_core, &
+                            RHO_TOP_OC,minus_g_cmb, &
+                            SIMULATION_TYPE,NSPEC2D_BOTTOM(IREGION_CRUST_MANTLE))
+
+    !---
+    !--- couple with outer core at the top of the inner core
+    !---
+    if(ACTUALLY_COUPLE_FLUID_ICB) &
+      call compute_coupling_ICB_fluid(displ_inner_core,b_displ_inner_core, &
+                            accel_inner_core,b_accel_inner_core, &
+                            ibool_inner_core,ibelm_top_inner_core,  &
+                            accel_outer_core,b_accel_outer_core, &
+                            normal_bottom_outer_core,jacobian2D_bottom_outer_core, &
+                            wgllwgll_xy,ibool_outer_core,ibelm_bottom_outer_core, &
+                            RHO_BOTTOM_OC,minus_g_icb, &
+                            SIMULATION_TYPE,NSPEC2D_TOP(IREGION_INNER_CORE))
+
+
+    ! assemble all the contributions between slices using MPI
+
+! assemble all the contributions between slices using MPI
+! crust/mantle and inner core handled in the same call
+! in order to reduce the number of MPI messages by 2
+    if(USE_NONBLOCKING_COMMS) then
+
+      iphase = 1 ! initialize the non blocking communication counter
+      iphase_CC = 1 ! initialize the non blocking communication counter for the central cube
+
+! start the non blocking communications
+      call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
+            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,iphase)
+
+      icall = 2 ! now compute all the inner elements in the case of non blocking MPI
+
+      ! compute internal forces in the solid regions
+
+      ! for anisotropy and gravity, x y and z contain r theta and phi
+
+      if( USE_DEVILLE_PRODUCTS_VAL ) then
+        call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_crust_mantle,accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,icall, &
+            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT, &
+          hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+      !---idoubling_crust_mantle, &
+          R_memory_crust_mantle,epsilondev_crust_mantle, &
+          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          alphaval,betaval,gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+      else
+        call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_crust_mantle,accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,icall, &
+            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz, &
+          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+      ! --idoubling_crust_mantle, &
+          R_memory_crust_mantle,epsilondev_crust_mantle, &
+          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          alphaval,betaval,gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+      endif
+
+      ! Deville routine
+      if( USE_DEVILLE_PRODUCTS_VAL ) then
+        call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_inner_core,accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,icall, &
+            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          alphaval,betaval,gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+      else
+        call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          displ_inner_core,accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,icall, &
+            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          alphaval,betaval,gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+      endif
+
+! assemble all the contributions between slices using MPI
+! crust/mantle and inner core handled in the same call
+! in order to reduce the number of MPI messages by 2
+      do while (iphase <= 7) ! make sure the last communications are finished and processed
+        call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
+            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,iphase)
+      enddo
+    else
+      ! crust/mantle and inner core handled in the same call
+      ! in order to reduce the number of MPI messages by 2
+      call assemble_MPI_vector_block(myrank, &
+            accel_crust_mantle,NGLOB_CRUST_MANTLE, &
+            accel_inner_core,NGLOB_INNER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
+            iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core, &
+            iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces,imsg_type, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            buffer_send_faces,buffer_received_faces, &
+            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL, &
+            NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_CRUST_MANTLE),NGLOB2DMAX_YMIN_YMAX(IREGION_CRUST_MANTLE), &
+            NGLOB1D_RADIAL(IREGION_INNER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_INNER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_INNER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL)
+    endif
+
+    !---
+    !---  use buffers to assemble forces with the central cube
+    !---
+
+    if(INCLUDE_CENTRAL_CUBE) then
+      if(USE_NONBLOCKING_COMMS) then
+        do while (iphase_CC <= 4) ! make sure the last communications are finished and processed
+          call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
+            ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),accel_inner_core,NDIM,iphase_CC)
+        enddo
+      else
+        call assemble_MPI_central_cube_block(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+          npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,buffer_slices2,ibool_central_cube, &
+          receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core,NSPEC_INNER_CORE, &
+          ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),NGLOB_INNER_CORE,accel_inner_core,NDIM)
+      endif
+    endif   ! end of assembling forces with the central cube
+
+#ifdef _HANDOPT
+! way 2:
+    if(imodulo_NGLOB_CRUST_MANTLE4 >= 1) then
+      do i=1,imodulo_NGLOB_CRUST_MANTLE4
+        accel_crust_mantle(1,i) = accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
+               + two_omega_earth*veloc_crust_mantle(2,i)
+        accel_crust_mantle(2,i) = accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
+               - two_omega_earth*veloc_crust_mantle(1,i)
+        accel_crust_mantle(3,i) = accel_crust_mantle(3,i)*rmass_crust_mantle(i)
+      enddo
+    endif
+    do i=imodulo_NGLOB_CRUST_MANTLE4+1,NGLOB_CRUST_MANTLE,4
+      accel_crust_mantle(1,i) = accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
+               + two_omega_earth*veloc_crust_mantle(2,i)
+      accel_crust_mantle(2,i) = accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
+               - two_omega_earth*veloc_crust_mantle(1,i)
+      accel_crust_mantle(3,i) = accel_crust_mantle(3,i)*rmass_crust_mantle(i)
+
+      accel_crust_mantle(1,i+1) = accel_crust_mantle(1,i+1)*rmass_crust_mantle(i+1) &
+               + two_omega_earth*veloc_crust_mantle(2,i+1)
+      accel_crust_mantle(2,i+1) = accel_crust_mantle(2,i+1)*rmass_crust_mantle(i+1) &
+               - two_omega_earth*veloc_crust_mantle(1,i+1)
+      accel_crust_mantle(3,i+1) = accel_crust_mantle(3,i+1)*rmass_crust_mantle(i+1)
+
+      accel_crust_mantle(1,i+2) = accel_crust_mantle(1,i+2)*rmass_crust_mantle(i+2) &
+               + two_omega_earth*veloc_crust_mantle(2,i+2)
+      accel_crust_mantle(2,i+2) = accel_crust_mantle(2,i+2)*rmass_crust_mantle(i+2) &
+               - two_omega_earth*veloc_crust_mantle(1,i+2)
+      accel_crust_mantle(3,i+2) = accel_crust_mantle(3,i+2)*rmass_crust_mantle(i+2)
+
+      accel_crust_mantle(1,i+3) = accel_crust_mantle(1,i+3)*rmass_crust_mantle(i+3) &
+               + two_omega_earth*veloc_crust_mantle(2,i+3)
+      accel_crust_mantle(2,i+3) = accel_crust_mantle(2,i+3)*rmass_crust_mantle(i+3) &
+               - two_omega_earth*veloc_crust_mantle(1,i+3)
+      accel_crust_mantle(3,i+3) = accel_crust_mantle(3,i+3)*rmass_crust_mantle(i+3)
+    enddo
+#else
+! way 1:
+    do i=1,NGLOB_CRUST_MANTLE
+      accel_crust_mantle(1,i) = accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
+               + two_omega_earth*veloc_crust_mantle(2,i)
+      accel_crust_mantle(2,i) = accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
+               - two_omega_earth*veloc_crust_mantle(1,i)
+      accel_crust_mantle(3,i) = accel_crust_mantle(3,i)*rmass_crust_mantle(i)
+    enddo
+#endif
+
+    if (SIMULATION_TYPE == 3) then
+
+! ------------------- new non blocking implementation -------------------
+
+      ! assemble all the contributions between slices using MPI
+
+! assemble all the contributions between slices using MPI
+! crust/mantle and inner core handled in the same call
+! in order to reduce the number of MPI messages by 2
+      if(USE_NONBLOCKING_COMMS) then
+
+        b_iphase = 1 ! initialize the non blocking communication counter
+        b_iphase_CC = 1 ! initialize the non blocking communication counter for the central cube
+
+! start the non blocking communications
+        call assemble_MPI_vector(myrank,b_accel_crust_mantle,b_accel_inner_core, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
+            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,b_iphase)
+
+        b_icall = 2 ! now compute all the inner elements in the case of non blocking MPI
+
+        ! compute internal forces in the solid regions
+
+        ! for anisotropy and gravity, x y and z contain r theta and phi
+
+        if( USE_DEVILLE_PRODUCTS_VAL ) then
+          call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_crust_mantle,b_accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,b_icall, &
+            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT, &
+          hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+      ! --idoubling_crust_mantle, &
+          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
+          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+        else
+          call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_crust_mantle,b_accel_crust_mantle, &
+          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+!----------------------
+            is_on_a_slice_edge_crust_mantle,b_icall, &
+            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz, &
+          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
+          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
+          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
+          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
+          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
+          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
+          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+      !--idoubling_crust_mantle, &
+          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
+          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
+          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
+          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
+          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
+        endif
+
+        ! Deville routine
+        if( USE_DEVILLE_PRODUCTS_VAL ) then
+          call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_inner_core,b_accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,b_icall, &
+            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          b_alphaval,b_betaval,b_gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+        else
+          call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
+          b_displ_inner_core,b_accel_inner_core, &
+          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
+          xix_inner_core,xiy_inner_core,xiz_inner_core, &
+          etax_inner_core,etay_inner_core,etaz_inner_core, &
+          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
+!----------------------
+            is_on_a_slice_edge_inner_core,b_icall, &
+            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
+            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
+            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
+!----------------------
+          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
+          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
+          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
+          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
+          c13store_inner_core,c44store_inner_core, &
+          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
+          one_minus_sum_beta_inner_core, &
+          b_alphaval,b_betaval,b_gammaval, &
+          factor_common_inner_core, &
+          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
+          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
+        endif
+
+! assemble all the contributions between slices using MPI
+! crust/mantle and inner core handled in the same call
+! in order to reduce the number of MPI messages by 2
+        do while (b_iphase <= 7) ! make sure the last communications are finished and processed
+          call assemble_MPI_vector(myrank,b_accel_crust_mantle,b_accel_inner_core, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
+            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,b_iphase)
+        enddo
+      else
+        ! crust/mantle and inner core handled in the same call
+        ! in order to reduce the number of MPI messages by 2
+        call assemble_MPI_vector_block(myrank, &
+            b_accel_crust_mantle,NGLOB_CRUST_MANTLE, &
+            b_accel_inner_core,NGLOB_INNER_CORE, &
+            iproc_xi,iproc_eta,ichunk,addressing, &
+            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
+            iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
+            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
+            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
+            iboolleft_xi_inner_core,iboolright_xi_inner_core, &
+            iboolleft_eta_inner_core,iboolright_eta_inner_core, &
+            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
+            iboolfaces_inner_core,iboolcorner_inner_core, &
+            iprocfrom_faces,iprocto_faces,imsg_type, &
+            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
+            b_buffer_send_faces,b_buffer_received_faces, &
+            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector, &
+            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
+            NPROC_XI_VAL,NPROC_ETA_VAL, &
+            NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_CRUST_MANTLE),NGLOB2DMAX_YMIN_YMAX(IREGION_CRUST_MANTLE), &
+            NGLOB1D_RADIAL(IREGION_INNER_CORE), &
+            NGLOB2DMAX_XMIN_XMAX(IREGION_INNER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_INNER_CORE), &
+            NGLOB2DMAX_XY,NCHUNKS_VAL)
+      endif
+
+      !---
+      !---  use buffers to assemble forces with the central cube
+      !---
+
+      if(INCLUDE_CENTRAL_CUBE) then
+        if(USE_NONBLOCKING_COMMS) then
+          do while (b_iphase_CC <= 4) ! make sure the last communications are finished and processed
+            call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+              npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
+              receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
+              ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),b_accel_inner_core,NDIM,b_iphase_CC)
+          enddo
+        else
+          call assemble_MPI_central_cube_block(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
+            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,buffer_slices2,ibool_central_cube, &
+            receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core,NSPEC_INNER_CORE, &
+            ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),NGLOB_INNER_CORE,b_accel_inner_core,NDIM)
+        endif
+      endif   ! end of assembling forces with the central cube
+
+! ------------------- new non blocking implementation -------------------
+
+#ifdef _HANDOPT
+! way 2:
+      if( imodulo_NGLOB_CRUST_MANTLE4 >=1 ) then
+        do i=1,imodulo_NGLOB_CRUST_MANTLE4
+          b_accel_crust_mantle(1,i) = b_accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
+                 + b_two_omega_earth*b_veloc_crust_mantle(2,i)
+          b_accel_crust_mantle(2,i) = b_accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
+                 - b_two_omega_earth*b_veloc_crust_mantle(1,i)
+          b_accel_crust_mantle(3,i) = b_accel_crust_mantle(3,i)*rmass_crust_mantle(i)
+        enddo
+      endif
+      do i=imodulo_NGLOB_CRUST_MANTLE4+1,NGLOB_CRUST_MANTLE,4
+        b_accel_crust_mantle(1,i) = b_accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
+                 + b_two_omega_earth*b_veloc_crust_mantle(2,i)
+        b_accel_crust_mantle(2,i) = b_accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
+                 - b_two_omega_earth*b_veloc_crust_mantle(1,i)
+        b_accel_crust_mantle(3,i) = b_accel_crust_mantle(3,i)*rmass_crust_mantle(i)
+
+        b_accel_crust_mantle(1,i+1) = b_accel_crust_mantle(1,i+1)*rmass_crust_mantle(i+1) &
+                 + b_two_omega_earth*b_veloc_crust_mantle(2,i+1)
+        b_accel_crust_mantle(2,i+1) = b_accel_crust_mantle(2,i+1)*rmass_crust_mantle(i+1) &
+                 - b_two_omega_earth*b_veloc_crust_mantle(1,i+1)
+        b_accel_crust_mantle(3,i+1) = b_accel_crust_mantle(3,i+1)*rmass_crust_mantle(i+1)
+
+        b_accel_crust_mantle(1,i+2) = b_accel_crust_mantle(1,i+2)*rmass_crust_mantle(i+2) &
+                 + b_two_omega_earth*b_veloc_crust_mantle(2,i+2)
+        b_accel_crust_mantle(2,i+2) = b_accel_crust_mantle(2,i+2)*rmass_crust_mantle(i+2) &
+                 - b_two_omega_earth*b_veloc_crust_mantle(1,i+2)
+        b_accel_crust_mantle(3,i+2) = b_accel_crust_mantle(3,i+2)*rmass_crust_mantle(i+2)
+
+        b_accel_crust_mantle(1,i+3) = b_accel_crust_mantle(1,i+3)*rmass_crust_mantle(i+3) &
+                 + b_two_omega_earth*b_veloc_crust_mantle(2,i+3)
+        b_accel_crust_mantle(2,i+3) = b_accel_crust_mantle(2,i+3)*rmass_crust_mantle(i+3) &
+                 - b_two_omega_earth*b_veloc_crust_mantle(1,i+3)
+        b_accel_crust_mantle(3,i+3) = b_accel_crust_mantle(3,i+3)*rmass_crust_mantle(i+3)
+      enddo
+#else
+! way 1:
+      do i=1,NGLOB_CRUST_MANTLE
+        b_accel_crust_mantle(1,i) = b_accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
+                 + b_two_omega_earth*b_veloc_crust_mantle(2,i)
+        b_accel_crust_mantle(2,i) = b_accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
+                 - b_two_omega_earth*b_veloc_crust_mantle(1,i)
+        b_accel_crust_mantle(3,i) = b_accel_crust_mantle(3,i)*rmass_crust_mantle(i)
+      enddo
+#endif
+
+    endif ! SIMULATION_TYPE == 3
+
+    ! couples ocean with crust mantle
+    if(OCEANS_VAL) &
+      call compute_coupling_ocean(accel_crust_mantle,b_accel_crust_mantle, &
+                            rmass_crust_mantle,rmass_ocean_load,normal_top_crust_mantle, &
+                            ibool_crust_mantle,ibelm_top_crust_mantle, &
+                            updated_dof_ocean_load, &
+                            SIMULATION_TYPE,NSPEC2D_TOP(IREGION_CRUST_MANTLE))
+
+
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+    ! Newmark time scheme - corrector for elastic parts
+#ifdef _HANDOPT
+! way 2:
+    ! mantle
+    if( imodulo_NGLOB_CRUST_MANTLE4 >= 1 ) then
+      do i=1,imodulo_NGLOB_CRUST_MANTLE4
+        veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) + deltatover2*accel_crust_mantle(:,i)
+      enddo
+    endif
+    do i=imodulo_NGLOB_CRUST_MANTLE4+1,NGLOB_CRUST_MANTLE,4
+      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) + deltatover2*accel_crust_mantle(:,i)
+      veloc_crust_mantle(:,i+1) = veloc_crust_mantle(:,i+1) + deltatover2*accel_crust_mantle(:,i+1)
+      veloc_crust_mantle(:,i+2) = veloc_crust_mantle(:,i+2) + deltatover2*accel_crust_mantle(:,i+2)
+      veloc_crust_mantle(:,i+3) = veloc_crust_mantle(:,i+3) + deltatover2*accel_crust_mantle(:,i+3)
+    enddo
+
+    ! inner core  
+    if(imodulo_NGLOB_INNER_CORE >= 1) then
+      do i=1,imodulo_NGLOB_INNER_CORE
+        accel_inner_core(1,i) = accel_inner_core(1,i)*rmass_inner_core(i) &
+               + two_omega_earth*veloc_inner_core(2,i)
+        accel_inner_core(2,i) = accel_inner_core(2,i)*rmass_inner_core(i) &
+               - two_omega_earth*veloc_inner_core(1,i)
+        accel_inner_core(3,i) = accel_inner_core(3,i)*rmass_inner_core(i)
+
+        veloc_inner_core(:,i) = veloc_inner_core(:,i) + deltatover2*accel_inner_core(:,i)
+      enddo
+    endif
+    do i=imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE,3
+      accel_inner_core(1,i) = accel_inner_core(1,i)*rmass_inner_core(i) &
+             + two_omega_earth*veloc_inner_core(2,i)
+      accel_inner_core(2,i) = accel_inner_core(2,i)*rmass_inner_core(i) &
+             - two_omega_earth*veloc_inner_core(1,i)
+      accel_inner_core(3,i) = accel_inner_core(3,i)*rmass_inner_core(i)
+
+      accel_inner_core(1,i+1) = accel_inner_core(1,i+1)*rmass_inner_core(i+1) &
+             + two_omega_earth*veloc_inner_core(2,i+1)
+      accel_inner_core(2,i+1) = accel_inner_core(2,i+1)*rmass_inner_core(i+1) &
+             - two_omega_earth*veloc_inner_core(1,i+1)
+      accel_inner_core(3,i+1) = accel_inner_core(3,i+1)*rmass_inner_core(i+1)
+
+      accel_inner_core(1,i+2) = accel_inner_core(1,i+2)*rmass_inner_core(i+2) &
+             + two_omega_earth*veloc_inner_core(2,i+2)
+      accel_inner_core(2,i+2) = accel_inner_core(2,i+2)*rmass_inner_core(i+2) &
+             - two_omega_earth*veloc_inner_core(1,i+2)
+      accel_inner_core(3,i+2) = accel_inner_core(3,i+2)*rmass_inner_core(i+2)
+
+      veloc_inner_core(:,i) = veloc_inner_core(:,i) + deltatover2*accel_inner_core(:,i)
+      veloc_inner_core(:,i+1) = veloc_inner_core(:,i+1) + deltatover2*accel_inner_core(:,i+1)
+      veloc_inner_core(:,i+2) = veloc_inner_core(:,i+2) + deltatover2*accel_inner_core(:,i+2)
+    enddo
+#else
+! way 1:
+    ! mantle
+    do i=1,NGLOB_CRUST_MANTLE
+      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) + deltatover2*accel_crust_mantle(:,i)
+    enddo
+    ! inner core
+    do i=1,NGLOB_INNER_CORE
+      accel_inner_core(1,i) = accel_inner_core(1,i)*rmass_inner_core(i) &
+             + two_omega_earth*veloc_inner_core(2,i)
+      accel_inner_core(2,i) = accel_inner_core(2,i)*rmass_inner_core(i) &
+             - two_omega_earth*veloc_inner_core(1,i)
+      accel_inner_core(3,i) = accel_inner_core(3,i)*rmass_inner_core(i)
+
+      veloc_inner_core(:,i) = veloc_inner_core(:,i) + deltatover2*accel_inner_core(:,i)
+    enddo
+#endif
+
+    if (SIMULATION_TYPE == 3) then
+#ifdef _HANDOPT
+! way 2:
+      ! mantle
+      if( imodulo_NGLOB_CRUST_MANTLE4 >= 1 ) then
+        do i=1,imodulo_NGLOB_CRUST_MANTLE4
+          b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) + b_deltatover2*b_accel_crust_mantle(:,i)
+        enddo
+      endif
+      do i=imodulo_NGLOB_CRUST_MANTLE4+1,NGLOB_CRUST_MANTLE,4
+        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) + b_deltatover2*b_accel_crust_mantle(:,i)
+        b_veloc_crust_mantle(:,i+1) = b_veloc_crust_mantle(:,i+1) + b_deltatover2*b_accel_crust_mantle(:,i+1)
+        b_veloc_crust_mantle(:,i+2) = b_veloc_crust_mantle(:,i+2) + b_deltatover2*b_accel_crust_mantle(:,i+2)
+        b_veloc_crust_mantle(:,i+3) = b_veloc_crust_mantle(:,i+3) + b_deltatover2*b_accel_crust_mantle(:,i+3)
+      enddo
+      ! inner core
+      if(imodulo_NGLOB_INNER_CORE >= 1) then
+        do i=1,imodulo_NGLOB_INNER_CORE
+          b_accel_inner_core(1,i) = b_accel_inner_core(1,i)*rmass_inner_core(i) &
+            + b_two_omega_earth*b_veloc_inner_core(2,i)
+          b_accel_inner_core(2,i) = b_accel_inner_core(2,i)*rmass_inner_core(i) &
+            - b_two_omega_earth*b_veloc_inner_core(1,i)
+          b_accel_inner_core(3,i) = b_accel_inner_core(3,i)*rmass_inner_core(i)
+
+          b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) + b_deltatover2*b_accel_inner_core(:,i)
+        enddo
+      endif
+      do i=imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE,3
+        b_accel_inner_core(1,i) = b_accel_inner_core(1,i)*rmass_inner_core(i) &
+         + b_two_omega_earth*b_veloc_inner_core(2,i)
+        b_accel_inner_core(2,i) = b_accel_inner_core(2,i)*rmass_inner_core(i) &
+         - b_two_omega_earth*b_veloc_inner_core(1,i)
+        b_accel_inner_core(3,i) = b_accel_inner_core(3,i)*rmass_inner_core(i)
+
+        b_accel_inner_core(1,i+1) = b_accel_inner_core(1,i+1)*rmass_inner_core(i+1) &
+         + b_two_omega_earth*b_veloc_inner_core(2,i+1)
+        b_accel_inner_core(2,i+1) = b_accel_inner_core(2,i+1)*rmass_inner_core(i+1) &
+         - b_two_omega_earth*b_veloc_inner_core(1,i+1)
+        b_accel_inner_core(3,i+1) = b_accel_inner_core(3,i+1)*rmass_inner_core(i+1)
+
+        b_accel_inner_core(1,i+2) = b_accel_inner_core(1,i+2)*rmass_inner_core(i+2) &
+         + b_two_omega_earth*b_veloc_inner_core(2,i+2)
+        b_accel_inner_core(2,i+2) = b_accel_inner_core(2,i+2)*rmass_inner_core(i+2) &
+         - b_two_omega_earth*b_veloc_inner_core(1,i+2)
+        b_accel_inner_core(3,i+2) = b_accel_inner_core(3,i+2)*rmass_inner_core(i+2)
+
+        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) + b_deltatover2*b_accel_inner_core(:,i)
+        b_veloc_inner_core(:,i+1) = b_veloc_inner_core(:,i+1) + b_deltatover2*b_accel_inner_core(:,i+1)
+        b_veloc_inner_core(:,i+2) = b_veloc_inner_core(:,i+2) + b_deltatover2*b_accel_inner_core(:,i+2)
+
+      enddo
+#else    
+! way 1:
+      ! mantle
+      do i=1,NGLOB_CRUST_MANTLE
+        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) + b_deltatover2*b_accel_crust_mantle(:,i)
+      enddo
+      ! inner core
+      do i=1,NGLOB_INNER_CORE
+        b_accel_inner_core(1,i) = b_accel_inner_core(1,i)*rmass_inner_core(i) &
+         + b_two_omega_earth*b_veloc_inner_core(2,i)
+        b_accel_inner_core(2,i) = b_accel_inner_core(2,i)*rmass_inner_core(i) &
+         - b_two_omega_earth*b_veloc_inner_core(1,i)
+        b_accel_inner_core(3,i) = b_accel_inner_core(3,i)*rmass_inner_core(i)
+
+        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) + b_deltatover2*b_accel_inner_core(:,i)
+      enddo
+#endif
+
+    endif ! SIMULATION_TYPE == 3
+
+
+    ! restores last time snapshot saved for backward/reconstruction of wavefields
+    ! note: this is done here after the Newmark time scheme, otherwise the indexing for sources
+    !          and adjoint sources will become more complicated
+    !          that is, index it for adjoint sources will match index NSTEP - 1 for backward/reconstructed wavefields
+    if( SIMULATION_TYPE == 3 .and. it == 1 ) then
+      call read_forward_arrays(myrank, &
+                    b_displ_crust_mantle,b_veloc_crust_mantle,b_accel_crust_mantle, &
+                    b_displ_inner_core,b_veloc_inner_core,b_accel_inner_core, &
+                    b_displ_outer_core,b_veloc_outer_core,b_accel_outer_core, &
+                    b_R_memory_crust_mantle,b_R_memory_inner_core, &
+                    b_epsilondev_crust_mantle,b_epsilondev_inner_core, &
+                    b_A_array_rotation,b_B_array_rotation,LOCAL_PATH)
+    endif
+
+! write the seismograms with time shift
+
+! store the seismograms only if there is at least one receiver located in this slice
+  if (nrec_local > 0) then
+    if (SIMULATION_TYPE == 1) then
+      call compute_seismograms(nrec_local,nrec,displ_crust_mantle, &
+                                nu,hxir_store,hetar_store,hgammar_store, &
+                                scale_displ,ibool_crust_mantle, &
+                                ispec_selected_rec,number_receiver_global, &
+                                seismo_current,NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
+                                seismograms)
+
+    else if (SIMULATION_TYPE == 2) then
+      call compute_seismograms_adjoint(NSOURCES,nrec_local,displ_crust_mantle, &
+                    eps_trace_over_3_crust_mantle,epsilondev_crust_mantle, &
+                    nu_source,Mxx,Myy,Mzz,Mxy,Mxz,Myz, &
+                    hxir_store,hetar_store,hgammar_store, &
+                    hpxir_store,hpetar_store,hpgammar_store, &
+                    tshift_cmt,hdur_gaussian,DT,t0,scale_displ, &
+                    hprime_xx,hprime_yy,hprime_zz, &
+                    xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                    etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
+                    gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
+                    moment_der,sloc_der,stshift_der,shdur_der, &
+                    NTSTEP_BETWEEN_OUTPUT_SEISMOS,seismograms,deltat, &
+                    ibool_crust_mantle,ispec_selected_source,number_receiver_global, &
+                    NSTEP,it,nit_written)
+
+    else if (SIMULATION_TYPE == 3) then
+      call compute_seismograms_backward(nrec_local,nrec,b_displ_crust_mantle, &
+                                nu,hxir_store,hetar_store,hgammar_store, &
+                                scale_displ,ibool_crust_mantle, &
+                                ispec_selected_rec,number_receiver_global, &
+                                seismo_current,NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
+                                seismograms)
+
+    endif
+  endif ! nrec_local
+
+  ! write the current or final seismograms
+  if(seismo_current == NTSTEP_BETWEEN_OUTPUT_SEISMOS .or. it == it_end) then
+    if (SIMULATION_TYPE == 1 .or. SIMULATION_TYPE == 3) then
+      call write_seismograms(myrank,seismograms,number_receiver_global,station_name, &
+            network_name,stlat,stlon,stele,stbur, &
+            nrec,nrec_local,ANGULAR_WIDTH_XI_IN_DEGREES,NEX_XI,DT,t0,it_end, &
+            yr_SAC,jda_SAC,ho_SAC,mi_SAC,sec_SAC,t_cmt_SAC,t_shift_SAC, &
+            elat_SAC,elon_SAC,depth_SAC,event_name_SAC,cmt_lat_SAC,cmt_lon_SAC,&
+            cmt_depth_SAC,cmt_hdur_SAC,NPROCTOT_VAL, &
+            OUTPUT_SEISMOS_ASCII_TEXT,OUTPUT_SEISMOS_SAC_ALPHANUM, &
+            OUTPUT_SEISMOS_SAC_BINARY,ROTATE_SEISMOGRAMS_RT,NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
+            seismo_offset,seismo_current,WRITE_SEISMOGRAMS_BY_MASTER, &
+            SAVE_ALL_SEISMOS_IN_ONE_FILE,USE_BINARY_FOR_LARGE_FILE)
+      if(myrank==0) then
+        write(IMAIN,*)
+        write(IMAIN,*) ' Total number of time steps written: ', it-it_begin+1
+        write(IMAIN,*)
+      endif
+    else
+      if( nrec_local > 0 ) &
+        call write_adj_seismograms(seismograms,number_receiver_global, &
+                                  nrec_local,it,nit_written,DT, &
+                                  NSTEP,NTSTEP_BETWEEN_OUTPUT_SEISMOS,t0,LOCAL_PATH)
+        nit_written = it
+    endif
+    seismo_offset = seismo_offset + seismo_current
+    seismo_current = 0
+  endif
+
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+
+! kernel calculations
+  if (SIMULATION_TYPE == 3) then
+    ! crust mantle
+    call compute_kernels_crust_mantle(ibool_crust_mantle, &
+                          rho_kl_crust_mantle,beta_kl_crust_mantle, &
+                          alpha_kl_crust_mantle,cijkl_kl_crust_mantle, &
+                          accel_crust_mantle,b_displ_crust_mantle, &
+                          epsilondev_crust_mantle,b_epsilondev_crust_mantle, &
+                          eps_trace_over_3_crust_mantle,b_eps_trace_over_3_crust_mantle, &
+                          deltat)
+
+    ! outer core
+    call compute_kernels_outer_core(ibool_outer_core, &
+                        xix_outer_core,xiy_outer_core,xiz_outer_core, &
+                        etax_outer_core,etay_outer_core,etaz_outer_core, &
+                        gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
+                        hprime_xx,hprime_yy,hprime_zz, &
+                        displ_outer_core,accel_outer_core, &
+                        b_displ_outer_core,b_accel_outer_core, &
+                        vector_accel_outer_core,vector_displ_outer_core, &
+                        b_vector_displ_outer_core, &
+                        div_displ_outer_core,b_div_displ_outer_core, &
+                        rhostore_outer_core,kappavstore_outer_core, &
+                        rho_kl_outer_core,alpha_kl_outer_core, &
+                        deviatoric_outercore,nspec_beta_kl_outer_core,beta_kl_outer_core, &
+                        deltat)
+
+    ! inner core
+    call compute_kernels_inner_core(ibool_inner_core, &
+                          rho_kl_inner_core,beta_kl_inner_core, &
+                          alpha_kl_inner_core, &
+                          accel_inner_core,b_displ_inner_core, &
+                          epsilondev_inner_core,b_epsilondev_inner_core, &
+                          eps_trace_over_3_inner_core,b_eps_trace_over_3_inner_core, &
+                          deltat)
+
+!<YANGL
+    ! NOISE TOMOGRAPHY --- source strength kernel
+    if (NOISE_TOMOGRAPHY == 3)  &
+       call compute_kernels_strength_noise(nmovie_points,ibool_crust_mantle, &
+                          Sigma_kl_crust_mantle,displ_crust_mantle,deltat,it, &
+                          normal_x_noise,normal_y_noise,normal_z_noise, &
+                          NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie, &
+                          ibelm_top_crust_mantle)
+!>YANGL
+
+    ! --- boundary kernels ------
+    if (SAVE_BOUNDARY_MESH) then
+      fluid_solid_boundary = .false.
+      iregion_code = IREGION_CRUST_MANTLE
+
+      ! Moho
+      if (.not. SUPPRESS_CRUSTAL_MESH .and. HONOR_1D_SPHERICAL_MOHO) then
+        call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
+                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
+                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+            ! -- idoubling_crust_mantle, &
+                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
+                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
+                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
+                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
+                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
+                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
+                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+                 k_top,ibelm_moho_top,normal_moho,moho_kl_top,fluid_solid_boundary,NSPEC2D_MOHO)
+
+        call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
+                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
+                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+              ! --idoubling_crust_mantle, &
+                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
+                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
+                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
+                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
+                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
+                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
+                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+                 k_bot,ibelm_moho_bot,normal_moho,moho_kl_bot,fluid_solid_boundary,NSPEC2D_MOHO)
+
+        moho_kl = moho_kl + (moho_kl_top - moho_kl_bot) * deltat
+      endif
+
+      ! 400
+      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
+                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
+                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+            ! --idoubling_crust_mantle, &
+                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
+                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
+                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
+                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
+                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
+                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
+                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+                 k_top,ibelm_400_top,normal_400,d400_kl_top,fluid_solid_boundary,NSPEC2D_400)
+
+      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
+                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
+                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+              ! --idoubling_crust_mantle, &
+                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
+                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
+                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
+                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
+                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
+                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
+                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+                 k_bot,ibelm_400_bot,normal_400,d400_kl_bot,fluid_solid_boundary,NSPEC2D_400)
+
+      d400_kl = d400_kl + (d400_kl_top - d400_kl_bot) * deltat
+
+      ! 670
+      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
+                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
+                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+              ! --idoubling_crust_mantle, &
+                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
+                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
+                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
+                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
+                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
+                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
+                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+                 k_top,ibelm_670_top,normal_670,d670_kl_top,fluid_solid_boundary,NSPEC2D_670)
+
+      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
+                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
+                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+              ! --idoubling_crust_mantle, &
+                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
+                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
+                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
+                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
+                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
+                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
+                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+                 k_bot,ibelm_670_bot,normal_670,d670_kl_bot,fluid_solid_boundary,NSPEC2D_670)
+
+      d670_kl = d670_kl + (d670_kl_top - d670_kl_bot) * deltat
+
+      ! CMB
+      fluid_solid_boundary = .true.
+      iregion_code = IREGION_CRUST_MANTLE
+      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
+                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
+                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
+              ! -- idoubling_crust_mantle, &
+                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
+                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
+                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_crust_mantle,kappavstore_crust_mantle, muvstore_crust_mantle, &
+                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
+                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
+                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
+                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
+                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
+                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
+                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
+                 k_top,ibelm_bottom_crust_mantle,normal_top_outer_core, &
+                 cmb_kl_top,fluid_solid_boundary,NSPEC2D_CMB)
+
+      iregion_code = IREGION_OUTER_CORE
+      call compute_boundary_kernel(vector_displ_outer_core,vector_accel_outer_core, &
+                 b_vector_displ_outer_core,nspec_outer_core, &
+                 iregion_code,ystore_outer_core,zstore_outer_core,ibool_outer_core,ispec_is_tiso_outer_core, &
+              ! --idoubling_outer_core, &
+                 xix_outer_core,xiy_outer_core,xiz_outer_core, &
+                 etax_outer_core,etay_outer_core,etaz_outer_core,&
+                 gammax_outer_core,gammay_outer_core,gammaz_outer_core,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_outer_core,kappavstore_outer_core,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 k_bot,ibelm_top_outer_core,normal_top_outer_core, &
+                 cmb_kl_bot,fluid_solid_boundary,NSPEC2D_CMB)
+
+      cmb_kl = cmb_kl + (cmb_kl_top - cmb_kl_bot) * deltat
+
+      ! ICB
+      fluid_solid_boundary = .true.
+      call compute_boundary_kernel(vector_displ_outer_core,vector_accel_outer_core, &
+                 b_vector_displ_outer_core,nspec_outer_core, &
+                 iregion_code,ystore_outer_core,zstore_outer_core,ibool_outer_core,ispec_is_tiso_outer_core, &
+              ! --idoubling_outer_core, &
+                 xix_outer_core,xiy_outer_core,xiz_outer_core, &
+                 etax_outer_core,etay_outer_core,etaz_outer_core,&
+                 gammax_outer_core,gammay_outer_core,gammaz_outer_core,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_outer_core,kappavstore_outer_core,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 k_top,ibelm_bottom_outer_core,normal_bottom_outer_core, &
+                 icb_kl_top,fluid_solid_boundary,NSPEC2D_ICB)
+
+      iregion_code = IREGION_INNER_CORE
+      call compute_boundary_kernel(displ_inner_core,accel_inner_core, &
+                 b_displ_inner_core,nspec_inner_core,iregion_code, &
+                 ystore_inner_core,zstore_inner_core,ibool_inner_core,ispec_is_tiso_inner_core, &
+              ! -- idoubling_inner_core, &
+                 xix_inner_core,xiy_inner_core,xiz_inner_core, &
+                 etax_inner_core,etay_inner_core,etaz_inner_core,&
+                 gammax_inner_core,gammay_inner_core,gammaz_inner_core,hprime_xx,hprime_yy,hprime_zz, &
+                 rhostore_inner_core,kappavstore_inner_core,muvstore_inner_core, &
+                 dummy_array,dummy_array,dummy_array, &
+                 c11store_inner_core,c12store_inner_core,c13store_inner_core,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array,dummy_array, &
+                 c33store_inner_core,dummy_array,dummy_array, &
+                 dummy_array,c44store_inner_core,dummy_array,dummy_array, &
+                 dummy_array,dummy_array,dummy_array, &
+                 k_bot,ibelm_top_inner_core,normal_bottom_outer_core, &
+                 icb_kl_bot,fluid_solid_boundary,NSPEC2D_ICB)
+
+      icb_kl = icb_kl + (icb_kl_top - icb_kl_bot) * deltat
+    endif
+
+    ! approximate hessian
+    if( APPROXIMATE_HESS_KL ) then
+      call compute_kernels_hessian(ibool_crust_mantle, &
+                          hess_kl_crust_mantle,&
+                          accel_crust_mantle,b_accel_crust_mantle, &
+                          deltat)
+    endif
+
+  endif ! end computing kernels
+
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+
+!<YANGL
+  ! first step of noise tomography, i.e., save a surface movie at every time step
+  ! modified from the subroutine 'write_movie_surface'
+  if ( NOISE_TOMOGRAPHY == 1 ) then
+        call noise_save_surface_movie(displ_crust_mantle, &
+                            ibelm_top_crust_mantle,ibool_crust_mantle, &
+                            NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie,it)
+  endif
+!>YANGL
+
+  ! save movie on surface
+  if( MOVIE_SURFACE ) then
+    if( mod(it,NTSTEP_BETWEEN_FRAMES) == 0) then
+      ! save velocity here to avoid static offset on displacement for movies
+      call write_movie_surface(myrank,nmovie_points,scale_veloc,veloc_crust_mantle, &
+                    scale_displ,displ_crust_mantle, &
+                    xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
+                    store_val_x,store_val_y,store_val_z, &
+                    store_val_x_all,store_val_y_all,store_val_z_all, &
+                    store_val_ux,store_val_uy,store_val_uz, &
+                    store_val_ux_all,store_val_uy_all,store_val_uz_all, &
+                    ibelm_top_crust_mantle,ibool_crust_mantle, &
+                    NSPEC2D_TOP(IREGION_CRUST_MANTLE), &
+                    NIT,it,OUTPUT_FILES,MOVIE_VOLUME_TYPE)
+    endif
+  endif
+
+
+  ! save movie in full 3D mesh
+  if(MOVIE_VOLUME ) then
+    if( mod(it-MOVIE_START,NTSTEP_BETWEEN_FRAMES) == 0  &
+      .and. it >= MOVIE_START .and. it <= MOVIE_STOP) then
+
+      if (MOVIE_VOLUME_TYPE == 1) then  ! output strains
+
+        call  write_movie_volume_strains(myrank,npoints_3dmovie, &
+                    LOCAL_PATH,MOVIE_VOLUME_TYPE,MOVIE_COARSE, &
+                    it,eps_trace_over_3_crust_mantle,epsilondev_crust_mantle, &
+                    muvstore_crust_mantle_3dmovie, &
+                    mask_3dmovie,nu_3dmovie)
+
+      else if (MOVIE_VOLUME_TYPE == 2 .or. MOVIE_VOLUME_TYPE == 3) then
+        ! output the Time Integral of Strain, or \mu*TIS
+        call  write_movie_volume_strains(myrank,npoints_3dmovie, &
+                    LOCAL_PATH,MOVIE_VOLUME_TYPE,MOVIE_COARSE, &
+                    it,Ieps_trace_over_3_crust_mantle,Iepsilondev_crust_mantle, &
+                    muvstore_crust_mantle_3dmovie, &
+                    mask_3dmovie,nu_3dmovie)
+
+      else if (MOVIE_VOLUME_TYPE == 4) then ! output divergence and curl in whole volume
+
+        call write_movie_volume_divcurl(myrank,it,eps_trace_over_3_crust_mantle,&
+                        div_displ_outer_core, &
+                        accel_outer_core,kappavstore_outer_core,rhostore_outer_core,ibool_outer_core, &
+                        eps_trace_over_3_inner_core, &
+                        epsilondev_crust_mantle,epsilondev_inner_core, &
+                        LOCAL_PATH, &
+                        displ_crust_mantle,displ_inner_core,displ_outer_core, &
+                        veloc_crust_mantle,veloc_inner_core,veloc_outer_core, &
+                        accel_crust_mantle,accel_inner_core, &                        
+                        ibool_crust_mantle,ibool_inner_core)
+
+      else if (MOVIE_VOLUME_TYPE == 5) then !output displacement
+        scalingval = scale_displ
+        call write_movie_volume_vector(myrank,it,npoints_3dmovie, &
+                    LOCAL_PATH,MOVIE_VOLUME_TYPE, &
+                    MOVIE_COARSE,ibool_crust_mantle,displ_crust_mantle, &
+                    scalingval,mask_3dmovie,nu_3dmovie)
+
+      else if (MOVIE_VOLUME_TYPE == 6) then !output velocity
+        scalingval = scale_veloc
+        call write_movie_volume_vector(myrank,it,npoints_3dmovie, &
+                    LOCAL_PATH,MOVIE_VOLUME_TYPE, &
+                    MOVIE_COARSE,ibool_crust_mantle,veloc_crust_mantle, &
+                    scalingval,mask_3dmovie,nu_3dmovie)
+
+      else
+
+        call exit_MPI(myrank, 'MOVIE_VOLUME_TYPE has to be 1,2,3,4,5 or 6')
+
+      endif ! MOVIE_VOLUME_TYPE
+    endif
+  endif ! MOVIE_VOLUME
+
+!daniel: debugging
+!  if( SNAPSHOT_INNER_CORE .and. mod(it-MOVIE_START,NTSTEP_BETWEEN_FRAMES) == 0  &
+!      .and. it >= MOVIE_START .and. it <= MOVIE_STOP) then
+!    ! VTK file output
+!    ! displacement values
+!    !write(prname,'(a,i6.6,a)') trim(LOCAL_PATH)//'/'//'proc',myrank,'_'
+!    !write(filename,'(a,a,i6.6)') prname(1:len_trim(prname)),'reg_3_displ_',it
+!    !call write_VTK_data_cr(idoubling_inner_core,NSPEC_INNER_CORE,NGLOB_INNER_CORE, &
+!    !                    xstore_inner_core,ystore_inner_core,zstore_inner_core,ibool_inner_core, &
+!    !                    displ_inner_core,filename)
+!
+!    write(prname,'(a)') 'OUTPUT_FILES/snapshot_all_'
+!    write(filename,'(a,a,i6.6)') prname(1:len_trim(prname)),'reg_3_displ_',it
+!    call write_VTK_data_cr_all(myrank,idoubling_inner_core, &
+!                        NSPEC_INNER_CORE,NGLOB_INNER_CORE, &
+!                        xstore_inner_core,ystore_inner_core,zstore_inner_core,ibool_inner_core, &
+!                        displ_inner_core,filename)
+!
+!  endif
+
+
+!---- end of time iteration loop
+!
+  enddo   ! end of main time loop
+!
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------------------------
+!
+
+  ! synchronize all processes, waits until all processes have written their seismograms
+  call MPI_BARRIER(MPI_COMM_WORLD,ier)
+  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize after time loop')
+
+  ! closes Stacey absorbing boundary snapshots
+  if( ABSORBING_CONDITIONS ) then
+    ! crust mantle
+    if (nspec2D_xmin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(0)
+    endif
+
+    if (nspec2D_xmax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(1)
+    endif
+
+    if (nspec2D_ymin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(2)
+    endif
+
+    if (nspec2D_ymax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(3)
+    endif
+
+    ! outer core
+    if (nspec2D_xmin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(4)
+    endif
+
+    if (nspec2D_xmax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(5)
+    endif
+
+    if (nspec2D_ymin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(6)
+    endif
+
+    if (nspec2D_ymax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(7)
+    endif
+
+    if (NSPEC2D_BOTTOM(IREGION_OUTER_CORE) > 0 .and. (SIMULATION_TYPE == 3 &
+      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
+      call close_file_abs(8)
+    endif
+
+  endif
+
+  ! save/read the surface movie using the same c routine as we do for absorbing boundaries (file ID is 9)
+  if (NOISE_TOMOGRAPHY/=0) then
+    call close_file_abs(9)
+    deallocate(noise_surface_movie)
+  endif
+
+
+  ! synchronize all processes
+  call MPI_BARRIER(MPI_COMM_WORLD,ier)
+  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize closing snapshots')
+
+  ! save files to local disk or tape system if restart file
+  call save_forward_arrays(myrank,SIMULATION_TYPE,SAVE_FORWARD, &
+                    NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN, &
+                    displ_crust_mantle,veloc_crust_mantle,accel_crust_mantle, &
+                    displ_inner_core,veloc_inner_core,accel_inner_core, &
+                    displ_outer_core,veloc_outer_core,accel_outer_core, &
+                    R_memory_crust_mantle,R_memory_inner_core, &
+                    epsilondev_crust_mantle,epsilondev_inner_core, &
+                    A_array_rotation,B_array_rotation, &
+                    LOCAL_PATH)
+
+  ! synchronize all processes
+  call MPI_BARRIER(MPI_COMM_WORLD,ier)
+  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize saving forward')
+
+  ! dump kernel arrays
+  if (SIMULATION_TYPE == 3) then
+    ! crust mantle
+    call save_kernels_crust_mantle(myrank,scale_t,scale_displ, &
+                  cijkl_kl_crust_mantle,rho_kl_crust_mantle, &
+                  alpha_kl_crust_mantle,beta_kl_crust_mantle, &
+                  ystore_crust_mantle,zstore_crust_mantle, &
+                  rhostore_crust_mantle,muvstore_crust_mantle, &
+                  kappavstore_crust_mantle,ibool_crust_mantle, &
+                  kappahstore_crust_mantle,muhstore_crust_mantle, &
+                  eta_anisostore_crust_mantle,ispec_is_tiso_crust_mantle, &
+              ! --idoubling_crust_mantle, &
+                  LOCAL_PATH)
+
+!<YANGL
+    ! noise strength kernel
+    if (NOISE_TOMOGRAPHY == 3) then
+       call save_kernels_strength_noise(myrank,LOCAL_PATH,Sigma_kl_crust_mantle)
+    endif
+!>YANGL
+
+    ! outer core
+    call save_kernels_outer_core(myrank,scale_t,scale_displ, &
+                        rho_kl_outer_core,alpha_kl_outer_core, &
+                        rhostore_outer_core,kappavstore_outer_core, &
+                        deviatoric_outercore,nspec_beta_kl_outer_core,beta_kl_outer_core, &
+                        LOCAL_PATH)
+
+    ! inner core
+    call save_kernels_inner_core(myrank,scale_t,scale_displ, &
+                          rho_kl_inner_core,beta_kl_inner_core,alpha_kl_inner_core, &
+                          rhostore_inner_core,muvstore_inner_core,kappavstore_inner_core, &
+                          LOCAL_PATH)
+
+    ! boundary kernel
+    if (SAVE_BOUNDARY_MESH) then
+      call save_kernels_boundary_kl(myrank,scale_t,scale_displ, &
+                                  moho_kl,d400_kl,d670_kl,cmb_kl,icb_kl, &
+                                  LOCAL_PATH,HONOR_1D_SPHERICAL_MOHO)
+    endif
+
+    ! approximate hessian
+    if( APPROXIMATE_HESS_KL ) then
+      call save_kernels_hessian(myrank,scale_t,scale_displ, &
+                                            hess_kl_crust_mantle,LOCAL_PATH)
+    endif
+  endif
+
+  ! save source derivatives for adjoint simulations
+  if (SIMULATION_TYPE == 2 .and. nrec_local > 0) then
+    call save_kernels_source_derivatives(nrec_local,NSOURCES,scale_displ,scale_t, &
+                                nu_source,moment_der,sloc_der,stshift_der,shdur_der,number_receiver_global)
+  endif
+
+  ! close the main output file
+  if(myrank == 0) then
+    write(IMAIN,*)
+    write(IMAIN,*) 'End of the simulation'
+    write(IMAIN,*)
+    close(IMAIN)
+  endif
+
+  ! synchronize all the processes to make sure everybody has finished
+  call MPI_BARRIER(MPI_COMM_WORLD,ier)
+  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize finishing simulation')
+
+  ! stop all the MPI processes, and exit
+  call MPI_FINALIZE(ier)
+
+  end program xspecfem3D
+

Deleted: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/specfem3D.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -1,4512 +0,0 @@
-!=====================================================================
-!
-!          S p e c f e m 3 D  G l o b e  V e r s i o n  5 . 1
-!          --------------------------------------------------
-!
-!          Main authors: Dimitri Komatitsch and Jeroen Tromp
-!                        Princeton University, USA
-!             and University of Pau / CNRS / INRIA, France
-! (c) Princeton University / California Institute of Technology and University of Pau / CNRS / INRIA
-!                            April 2011
-!
-! This program is free software; you can redistribute it and/or modify
-! it under the terms of the GNU General Public License as published by
-! the Free Software Foundation; either version 2 of the License, or
-! (at your option) any later version.
-!
-! This program is distributed in the hope that it will be useful,
-! but WITHOUT ANY WARRANTY; without even the implied warranty of
-! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-! GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along
-! with this program; if not, write to the Free Software Foundation, Inc.,
-! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-!
-!=====================================================================
-!
-! United States and French Government Sponsorship Acknowledged.
-
-  program xspecfem3D
-
-  implicit none
-
-! standard include of the MPI library
-  include 'mpif.h'
-
-  include "constants.h"
-  include "precision.h"
-
-! include values created by the mesher
-  include "OUTPUT_FILES/values_from_mesher.h"
-
-!=======================================================================!
-!                                                                       !
-!   specfem3D is a 3-D spectral-element solver for the Earth.           !
-!   It uses a mesh generated by program meshfem3D                       !
-!                                                                       !
-!=======================================================================!
-!
-! If you use this code for your own research, please cite at least one article
-! written by the developers of the package, for instance:
-!
-! @ARTICLE{TrKoLi08,
-! author = {Jeroen Tromp and Dimitri Komatitsch and Qinya Liu},
-! title = {Spectral-Element and Adjoint Methods in Seismology},
-! journal = {Communications in Computational Physics},
-! year = {2008},
-! volume = {3},
-! pages = {1-32},
-! number = {1}}
-!
-! or
-!
-! @ARTICLE{VaCaSaKoVi99,
-! author = {R. Vai and J. M. Castillo-Covarrubias and F. J. S\'anchez-Sesma and
-! D. Komatitsch and J. P. Vilotte},
-! title = {Elastic wave propagation in an irregularly layered medium},
-! journal = {Soil Dynamics and Earthquake Engineering},
-! year = {1999},
-! volume = {18},
-! pages = {11-18},
-! number = {1},
-! doi = {10.1016/S0267-7261(98)00027-X}}
-!
-! @ARTICLE{LeChKoHuTr09,
-! author = {Shiann Jong Lee and Yu Chang Chan and Dimitri Komatitsch and Bor
-! Shouh Huang and Jeroen Tromp},
-! title = {Effects of realistic surface topography on seismic ground motion
-! in the {Y}angminshan region of {T}aiwan based upon the spectral-element
-! method and {LiDAR DTM}},
-! journal = {Bull. Seismol. Soc. Am.},
-! year = {2009},
-! volume = {99},
-! pages = {681-693},
-! number = {2A},
-! doi = {10.1785/0120080264}}
-!
-! @ARTICLE{LeChLiKoHuTr08,
-! author = {Shiann Jong Lee and How Wei Chen and Qinya Liu and Dimitri Komatitsch
-! and Bor Shouh Huang and Jeroen Tromp},
-! title = {Three-Dimensional Simulations of Seismic Wave Propagation in the
-! {T}aipei Basin with Realistic Topography Based upon the Spectral-Element Method},
-! journal = {Bull. Seismol. Soc. Am.},
-! year = {2008},
-! volume = {98},
-! pages = {253-264},
-! number = {1},
-! doi = {10.1785/0120070033}}
-!
-! @ARTICLE{LeKoHuTr09,
-! author = {S. J. Lee and Dimitri Komatitsch and B. S. Huang and J. Tromp},
-! title = {Effects of topography on seismic wave propagation: An example from
-! northern {T}aiwan},
-! journal = {Bull. Seismol. Soc. Am.},
-! year = {2009},
-! volume = {99},
-! pages = {314-325},
-! number = {1},
-! doi = {10.1785/0120080020}}
-!
-! @ARTICLE{KoErGoMi10,
-! author = {Dimitri Komatitsch and Gordon Erlebacher and Dominik G\"oddeke and
-! David Mich\'ea},
-! title = {High-order finite-element seismic wave propagation modeling with
-! {MPI} on a large {GPU} cluster},
-! journal = {J. Comput. Phys.},
-! year = {2010},
-! volume = {229},
-! pages = {7692-7714},
-! number = {20},
-! doi = {10.1016/j.jcp.2010.06.024}}
-!
-! @ARTICLE{KoGoErMi10,
-! author = {Dimitri Komatitsch and Dominik G\"oddeke and Gordon Erlebacher and
-! David Mich\'ea},
-! title = {Modeling the propagation of elastic waves using spectral elements
-! on a cluster of 192 {GPU}s},
-! journal = {Computer Science Research and Development},
-! year = {2010},
-! volume = {25},
-! pages = {75-82},
-! number = {1-2},
-! doi = {10.1007/s00450-010-0109-1}}
-!
-! @ARTICLE{KoMiEr09,
-! author = {Dimitri Komatitsch and David Mich\'ea and Gordon Erlebacher},
-! title = {Porting a high-order finite-element earthquake modeling application
-! to {NVIDIA} graphics cards using {CUDA}},
-! journal = {Journal of Parallel and Distributed Computing},
-! year = {2009},
-! volume = {69},
-! pages = {451-460},
-! number = {5},
-! doi = {10.1016/j.jpdc.2009.01.006}}
-!
-! @INCOLLECTION{ChKoViCaVaFe07,
-! author = {Emmanuel Chaljub and Dimitri Komatitsch and Jean-Pierre Vilotte and
-! Yann Capdeville and Bernard Valette and Gaetano Festa},
-! title = {Spectral Element Analysis in Seismology},
-! booktitle = {Advances in Wave Propagation in Heterogeneous Media},
-! publisher = {Elsevier - Academic Press},
-! year = {2007},
-! editor = {Ru-Shan Wu and Val\'erie Maupin},
-! volume = {48},
-! series = {Advances in Geophysics},
-! pages = {365-419}}
-!
-! @ARTICLE{KoVi98,
-! author={D. Komatitsch and J. P. Vilotte},
-! title={The spectral-element method: an efficient tool to simulate the seismic response of 2{D} and 3{D} geological structures},
-! journal={Bull. Seismol. Soc. Am.},
-! year=1998,
-! volume=88,
-! number=2,
-! pages={368-392}}
-!
-! @ARTICLE{KoTr99,
-! author={D. Komatitsch and J. Tromp},
-! year=1999,
-! title={Introduction to the spectral-element method for 3-{D} seismic wave propagation},
-! journal={Geophys. J. Int.},
-! volume=139,
-! number=3,
-! pages={806-822},
-! doi={10.1046/j.1365-246x.1999.00967.x}}
-!
-! @ARTICLE{KoRiTr02,
-! author={D. Komatitsch and J. Ritsema and J. Tromp},
-! year=2002,
-! title={The Spectral-Element Method, {B}eowulf Computing, and Global Seismology},
-! journal={Science},
-! volume=298,
-! number=5599,
-! pages={1737-1742},
-! doi={10.1126/science.1076024}}
-!
-! @ARTICLE{KoTr02a,
-! author={D. Komatitsch and J. Tromp},
-! year=2002,
-! title={Spectral-Element Simulations of Global Seismic Wave Propagation{-I. V}alidation},
-! journal={Geophys. J. Int.},
-! volume=149,
-! number=2,
-! pages={390-412},
-! doi={10.1046/j.1365-246X.2002.01653.x}}
-!
-! @ARTICLE{KoTr02b,
-! author={D. Komatitsch and J. Tromp},
-! year=2002,
-! title={Spectral-Element Simulations of Global Seismic Wave Propagation{-II. 3-D} Models, Oceans, Rotation, and Self-Gravitation},
-! journal={Geophys. J. Int.},
-! volume=150,
-! pages={303-318},
-! number=1,
-! doi={10.1046/j.1365-246X.2002.01716.x}}
-!
-! and/or another article from http://web.univ-pau.fr/~dkomati1/publications.html
-!
-!
-! If you use the kernel capabilities of the code, please cite at least one article
-! written by the developers of the package, for instance:
-!
-! @ARTICLE{TrKoLi08,
-! author = {Jeroen Tromp and Dimitri Komatitsch and Qinya Liu},
-! title = {Spectral-Element and Adjoint Methods in Seismology},
-! journal = {Communications in Computational Physics},
-! year = {2008},
-! volume = {3},
-! pages = {1-32},
-! number = {1}}
-!
-! or
-!
-! @ARTICLE{LiTr06,
-! author={Qinya Liu and Jeroen Tromp},
-! title={Finite-frequency kernels based on adjoint methods},
-! journal={Bull. Seismol. Soc. Am.},
-! year=2006,
-! volume=96,
-! number=6,
-! pages={2383-2397},
-! doi={10.1785/0120060041}}
-!
-! If you use 3-D model S20RTS, please cite:
-!
-! @ARTICLE{RiVa00,
-! author={J. Ritsema and H. J. {Van Heijst}},
-! year=2000,
-! title={Seismic imaging of structural heterogeneity in {E}arth's mantle: Evidence for large-scale mantle flow},
-! journal={Science Progress},
-! volume=83,
-! pages={243-259}}
-!
-! Reference frame - convention:
-! ----------------------------
-!
-! The code uses the following convention for the reference frame:
-!
-!  - X axis is East
-!  - Y axis is North
-!  - Z axis is up
-!
-! Note that this convention is different from both the Aki-Richards convention
-! and the Harvard CMT convention.
-!
-! Let us recall that the Aki-Richards convention is:
-!
-!  - X axis is North
-!  - Y axis is East
-!  - Z axis is down
-!
-! and that the Harvard CMT convention is:
-!
-!  - X axis is South
-!  - Y axis is East
-!  - Z axis is up
-!
-! To report bugs or suggest improvements to the code, please send an email
-! to Jeroen Tromp <jtromp AT princeton.edu> and/or use our online
-! bug tracking system at http://www.geodynamics.org/roundup .
-!
-! Evolution of the code:
-! ---------------------
-!
-! v. 5.1, Dimitri Komatitsch, University of Toulouse, France and Ebru Bozdag, Princeton University, USA, February 2011:
-!     non blocking MPI for much better scaling on large clusters;
-!     new convention for the name of seismograms, to conform to the IRIS standard;
-!     new directory structure
-!
-! v. 5.0 aka Tiger, many developers some with Princeton Tiger logo on their shirts, February 2010:
-!     new moho mesh stretching honoring crust2.0 moho depths,
-!     new attenuation assignment, new SAC headers, new general crustal models,
-!     faster performance due to Deville routines and enhanced loop unrolling,
-!     slight changes in code structure (see also trivia at program start)
-!
-! v. 4.0 David Michea and Dimitri Komatitsch, University of Pau, France, February 2008:
-!      new doubling brick in the mesh, new perfectly load-balanced mesh,
-!      more flexible routines for mesh design, new inflated central cube
-!      with optimized shape, far fewer mesh files saved by the mesher,
-!      global arrays sorted to speed up the simulation, seismos can be
-!      written by the master, one more doubling level at the bottom
-!      of the outer core if needed (off by default)
-!
-! v. 3.6 Many people, many affiliations, September 2006:
-!      adjoint and kernel calculations, fixed IASP91 model,
-!      added AK135 and 1066a, fixed topography/bathymetry routine,
-!      new attenuation routines, faster and better I/Os on very large
-!      systems, many small improvements and bug fixes, new "configure"
-!      script, new Pyre version, new user's manual etc.
-!
-! v. 3.5 Dimitri Komatitsch, Brian Savage and Jeroen Tromp, Caltech, July 2004:
-!      any size of chunk, 3D attenuation, case of two chunks,
-!      more precise topography/bathymetry model, new Par_file structure
-!
-! v. 3.4 Dimitri Komatitsch and Jeroen Tromp, Caltech, August 2003:
-!      merged global and regional codes, no iterations in fluid, better movies
-!
-! v. 3.3 Dimitri Komatitsch, Caltech, September 2002:
-!      flexible mesh doubling in outer core, inlined code, OpenDX support
-!
-! v. 3.2 Jeroen Tromp, Caltech, July 2002:
-!      multiple sources and flexible PREM reading
-!
-! v. 3.1 Dimitri Komatitsch, Caltech, June 2002:
-!      vectorized loops in solver and merged central cube
-!
-! v. 3.0 Dimitri Komatitsch and Jeroen Tromp, Caltech, May 2002:
-!   ported to SGI and Compaq, double precision solver, more general anisotropy
-!
-! v. 2.3 Dimitri Komatitsch and Jeroen Tromp, Caltech, August 2001:
-!                       gravity, rotation, oceans and 3-D models
-!
-! v. 2.2 Dimitri Komatitsch and Jeroen Tromp, Caltech, USA, March 2001:
-!                       final MPI package
-!
-! v. 2.0 Dimitri Komatitsch, Harvard, USA, January 2000: MPI code for the globe
-!
-! v. 1.0 Dimitri Komatitsch, UNAM, Mexico, June 1999: first MPI code for a chunk
-!
-! Jeroen Tromp and Dimitri Komatitsch, Harvard, USA, July 1998: first chunk solver using OpenMP on a Sun machine
-!
-! Dimitri Komatitsch, IPG Paris, France, December 1996: first 3-D solver for the CM-5 Connection Machine,
-!    parallelized on 128 processors using Connection Machine Fortran
-!
-! From Dahlen and Tromp (1998):
-! ----------------------------
-!
-! Gravity is approximated by solving eq (3.259) without the Phi_E' term
-! The ellipsoidal reference model is that of section 14.1
-! The transversely isotropic expression for PREM is that of eq (8.190)
-!
-! Formulation in the fluid (acoustic) outer core:
-! -----------------------------------------------
-!
-! In case of an acoustic medium, a displacement potential Chi is used
-! as in Chaljub and Valette, Geophysical Journal International, vol. 158,
-! p. 131-141 (2004) and *NOT* a velocity potential as in Komatitsch and Tromp,
-! Geophysical Journal International, vol. 150, p. 303-318 (2002).
-! This permits acoustic-elastic coupling based on a non-iterative time scheme.
-! Displacement if we ignore gravity is then: u = grad(Chi)
-! (In the context of the Cowling approximation displacement is
-! u = grad(rho * Chi) / rho, *not* u = grad(Chi).)
-! Velocity is then: v = grad(Chi_dot)       (Chi_dot being the time derivative of Chi)
-! and pressure is: p = - rho * Chi_dot_dot  (Chi_dot_dot being the time second derivative of Chi).
-! The source in an acoustic element is a pressure source.
-! The potential in the outer core is called displ_outer_core for simplicity.
-! Its first time derivative is called veloc_outer_core.
-! Its second time derivative is called accel_outer_core.
-
-! memory variables and standard linear solids for attenuation
-  real(kind=CUSTOM_REAL), dimension(ATT1,ATT2,ATT3,ATT4) :: one_minus_sum_beta_crust_mantle, factor_scale_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(ATT1,ATT2,ATT3,ATT5) :: one_minus_sum_beta_inner_core, factor_scale_inner_core
-
-  real(kind=CUSTOM_REAL), dimension(N_SLS) :: alphaval, betaval, gammaval
-  real(kind=CUSTOM_REAL), dimension(N_SLS,ATT1,ATT2,ATT3,ATT4) :: factor_common_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(N_SLS,ATT1,ATT2,ATT3,ATT5) :: factor_common_inner_core
-
-  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ATTENUAT) :: R_memory_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_OR_ATT) :: epsilondev_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STRAIN_ONLY) :: eps_trace_over_3_crust_mantle
-
-  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ATTENUATION) :: R_memory_inner_core
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STR_OR_ATT) :: epsilondev_inner_core
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STRAIN_ONLY) :: eps_trace_over_3_inner_core
-
-! ADJOINT
-  real(kind=CUSTOM_REAL), dimension(N_SLS) :: b_alphaval, b_betaval, b_gammaval
-
-  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_AND_ATT) :: b_R_memory_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: b_epsilondev_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: b_eps_trace_over_3_crust_mantle
-
-  real(kind=CUSTOM_REAL), dimension(5,N_SLS,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STR_AND_ATT) :: b_R_memory_inner_core
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ADJOINT) :: b_epsilondev_inner_core
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ADJOINT) :: b_eps_trace_over_3_inner_core
-
-! for matching with central cube in inner core
-  integer, dimension(:), allocatable :: sender_from_slices_to_cube
-  integer, dimension(:,:), allocatable :: ibool_central_cube
-  double precision, dimension(:,:), allocatable :: buffer_slices,b_buffer_slices,buffer_slices2
-  double precision, dimension(:,:,:), allocatable :: buffer_all_cube_from_slices,b_buffer_all_cube_from_slices
-  integer nb_msgs_theor_in_cube,non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices,receiver_cube_from_slices
-
-  integer nspec2D_xmin_inner_core,nspec2D_xmax_inner_core,nspec2D_ymin_inner_core,nspec2D_ymax_inner_core
-
-! to save movie frames
-  integer nmovie_points,NIT
-  real(kind=CUSTOM_REAL), dimension(:), allocatable :: &
-      store_val_x,store_val_y,store_val_z, &
-      store_val_ux,store_val_uy,store_val_uz
-  real(kind=CUSTOM_REAL), dimension(:,:), allocatable :: &
-      store_val_x_all,store_val_y_all,store_val_z_all, &
-      store_val_ux_all,store_val_uy_all,store_val_uz_all
-
-! to save movie volume
-  integer :: npoints_3dmovie,nspecel_3dmovie
-  integer, dimension(NGLOB_CRUST_MANTLE) :: num_ibool_3dmovie
-  double precision :: scalingval
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_OR_ATT) :: muvstore_crust_mantle_3dmovie
-  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: nu_3dmovie
-  logical, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STRAIN_ONLY) :: mask_3dmovie
-
-  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STR_OR_ATT) :: Iepsilondev_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STRAIN_ONLY) :: Ieps_trace_over_3_crust_mantle
-
-! use integer array to store values
-  integer, dimension(NX_BATHY,NY_BATHY) :: ibathy_topo
-
-! for crust/oceans coupling
-  integer, dimension(NSPEC2DMAX_XMIN_XMAX_CM) :: ibelm_xmin_crust_mantle,ibelm_xmax_crust_mantle
-  integer, dimension(NSPEC2DMAX_YMIN_YMAX_CM) :: ibelm_ymin_crust_mantle,ibelm_ymax_crust_mantle
-  integer, dimension(NSPEC2D_BOTTOM_CM) :: ibelm_bottom_crust_mantle
-  integer, dimension(NSPEC2D_TOP_CM) :: ibelm_top_crust_mantle
-
-! additional mass matrix for ocean load
-  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE_OCEANS) :: rmass_ocean_load
-
-! flag to mask ocean-bottom degrees of freedom for ocean load
-  logical, dimension(NGLOB_CRUST_MANTLE_OCEANS) :: updated_dof_ocean_load
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_BOTTOM_CM) :: jacobian2D_bottom_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_TOP_CM) :: jacobian2D_top_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_CM) :: jacobian2D_xmin_crust_mantle,&
-  jacobian2D_xmax_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ,NSPEC2DMAX_YMIN_YMAX_CM) :: jacobian2D_ymin_crust_mantle,&
-  jacobian2D_ymax_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_CM) :: &
-  normal_xmin_crust_mantle,normal_xmax_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2DMAX_YMIN_YMAX_CM) :: &
-  normal_ymin_crust_mantle,normal_ymax_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_BOTTOM_CM) :: normal_bottom_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_TOP_CM) :: normal_top_crust_mantle
-
-! Stacey
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_STACEY) :: rho_vp_crust_mantle,rho_vs_crust_mantle
-  integer nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle,nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle
-  integer, dimension(2,NSPEC2DMAX_YMIN_YMAX_CM) :: nimin_crust_mantle,nimax_crust_mantle,nkmin_eta_crust_mantle
-  integer, dimension(2,NSPEC2DMAX_XMIN_XMAX_CM) :: njmin_crust_mantle,njmax_crust_mantle,nkmin_xi_crust_mantle
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_STACEY) :: vp_outer_core
-  integer nspec2D_xmin_outer_core,nspec2D_xmax_outer_core,nspec2D_ymin_outer_core,nspec2D_ymax_outer_core
-  integer, dimension(2,NSPEC2DMAX_YMIN_YMAX_OC) :: nimin_outer_core,nimax_outer_core,nkmin_eta_outer_core
-  integer, dimension(2,NSPEC2DMAX_XMIN_XMAX_OC) :: njmin_outer_core,njmax_outer_core,nkmin_xi_outer_core
-
-! arrays to couple with the fluid regions by pointwise matching
-  integer, dimension(NSPEC2DMAX_XMIN_XMAX_OC) :: ibelm_xmin_outer_core,ibelm_xmax_outer_core
-  integer, dimension(NSPEC2DMAX_YMIN_YMAX_OC) :: ibelm_ymin_outer_core,ibelm_ymax_outer_core
-  integer, dimension(NSPEC2D_BOTTOM_OC) :: ibelm_bottom_outer_core
-  integer, dimension(NSPEC2D_TOP_OC) :: ibelm_top_outer_core
-
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_OC) :: normal_xmin_outer_core,normal_xmax_outer_core
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLZ,NSPEC2DMAX_YMIN_YMAX_OC) :: normal_ymin_outer_core,normal_ymax_outer_core
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_BOTTOM_OC) :: normal_bottom_outer_core
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_TOP_OC) :: normal_top_outer_core
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_BOTTOM_OC) :: jacobian2D_bottom_outer_core
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_TOP_OC) :: jacobian2D_top_outer_core
-  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ,NSPEC2DMAX_XMIN_XMAX_OC) :: jacobian2D_xmin_outer_core,jacobian2D_xmax_outer_core
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ,NSPEC2DMAX_YMIN_YMAX_OC) :: jacobian2D_ymin_outer_core,jacobian2D_ymax_outer_core
-
-
-  integer, dimension(NSPEC2DMAX_XMIN_XMAX_IC) :: ibelm_xmin_inner_core,ibelm_xmax_inner_core
-  integer, dimension(NSPEC2DMAX_YMIN_YMAX_IC) :: ibelm_ymin_inner_core,ibelm_ymax_inner_core
-  integer, dimension(NSPEC2D_BOTTOM_IC) :: ibelm_bottom_inner_core
-  integer, dimension(NSPEC2D_TOP_IC) :: ibelm_top_inner_core
-
-! for ellipticity
-  integer nspl
-  double precision rspl(NR),espl(NR),espl2(NR)
-
-! for conversion from x y z to r theta phi
-  real(kind=CUSTOM_REAL) rval,thetaval,phival
-
-! ---- arrays to assemble between chunks
-
-! communication pattern for faces between chunks
-  integer, dimension(NUMMSGS_FACES_VAL) :: iprocfrom_faces,iprocto_faces,imsg_type
-
-! communication pattern for corners between chunks
-  integer, dimension(NCORNERSCHUNKS_VAL) :: iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners
-
-! indirect addressing for each message for faces and corners of the chunks
-! a given slice can belong to at most one corner and at most two faces
-  integer NGLOB2DMAX_XY
-  integer, dimension(NGLOB2DMAX_XY_VAL,NUMFACES_SHARED) :: iboolfaces_crust_mantle, &
-      iboolfaces_outer_core,iboolfaces_inner_core
-
-! this for non blocking MPI
-
-! buffers for send and receive between faces of the slices and the chunks
-! we use the same buffers to assemble scalars and vectors because vectors are
-! always three times bigger and therefore scalars can use the first part
-! of the vector buffer in memory even if it has an additional index here
-  integer :: npoin2D_max_all_CM_IC
-  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: buffer_send_faces,buffer_received_faces, &
-                                                           b_buffer_send_faces,b_buffer_received_faces
-
-! for non blocking communications
-  logical, dimension(NSPEC_CRUST_MANTLE) :: is_on_a_slice_edge_crust_mantle
-  logical, dimension(NSPEC_OUTER_CORE) :: is_on_a_slice_edge_outer_core
-  logical, dimension(NSPEC_INNER_CORE) :: is_on_a_slice_edge_inner_core
-  logical, dimension(NGLOB_CRUST_MANTLE) :: mask_ibool
-  real :: percentage_edge
-
-! assembling phase number for non blocking MPI
-! iphase is for the crust_mantle, outer_core and inner_core regions
-! iphase_CC is for the central cube
-  integer :: iphase,iphase_CC,icall
-  integer :: b_iphase,b_iphase_CC,b_icall
-
-! -------- arrays specific to each region here -----------
-
-! ----------------- crust, mantle and oceans ---------------------
-
-! mesh parameters
-  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool_crust_mantle
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: &
-        xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle,&
-        etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-        gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: &
-        xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle
-
-! arrays for isotropic elements stored only where needed to save space
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ISO_MANTLE) :: &
-        rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle
-
-! arrays for anisotropic elements stored only where needed to save space
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_TISO_MANTLE) :: &
-        kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle
-
-! arrays for full anisotropy only when needed
-  integer nspec_iso,nspec_tiso,nspec_ani
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_MANTLE) :: &
-        c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-        c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-        c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-        c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-        c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-        c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-        c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle
-
-! local to global mapping
-!  integer, dimension(NSPEC_CRUST_MANTLE) :: idoubling_crust_mantle
-  logical, dimension(NSPEC_CRUST_MANTLE) :: ispec_is_tiso_crust_mantle
-
-! mass matrix
-  real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: rmass_crust_mantle
-
-! displacement, velocity, acceleration
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: &
-     displ_crust_mantle,veloc_crust_mantle,accel_crust_mantle
-
-! ----------------- outer core ---------------------
-
-! mesh parameters
-  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: ibool_outer_core
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: &
-        xix_outer_core,xiy_outer_core,xiz_outer_core,&
-        etax_outer_core,etay_outer_core,etaz_outer_core, &
-        gammax_outer_core,gammay_outer_core,gammaz_outer_core
-  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: &
-        xstore_outer_core,ystore_outer_core,zstore_outer_core
-
- real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: &
-        rhostore_outer_core,kappavstore_outer_core
-
-! local to global mapping
-  integer, dimension(NSPEC_OUTER_CORE) :: idoubling_outer_core
-  logical, dimension(NSPEC_OUTER_CORE) :: ispec_is_tiso_outer_core ! only needed for compute_boundary_kernel()
-
-! mass matrix
-  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: rmass_outer_core
-
-! velocity potential
-  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: displ_outer_core, &
-    veloc_outer_core,accel_outer_core
-
-! ----------------- inner core ---------------------
-
-! mesh parameters
-  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool_inner_core
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: &
-        xix_inner_core,xiy_inner_core,xiz_inner_core,&
-        etax_inner_core,etay_inner_core,etaz_inner_core, &
-        gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-        rhostore_inner_core, kappavstore_inner_core,muvstore_inner_core
-  real(kind=CUSTOM_REAL), dimension(NGLOB_INNER_CORE) :: &
-        xstore_inner_core,ystore_inner_core,zstore_inner_core
-
-! arrays for inner-core anisotropy only when needed
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPECMAX_ANISO_IC) :: &
-        c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-        c13store_inner_core,c44store_inner_core
-
-! local to global mapping
-  integer, dimension(NSPEC_INNER_CORE) :: idoubling_inner_core
-  logical, dimension(NSPEC_INNER_CORE) :: ispec_is_tiso_inner_core ! only needed for computer_boundary_kernel() routine
-
-! mass matrix
-  real(kind=CUSTOM_REAL), dimension(NGLOB_INNER_CORE) :: rmass_inner_core
-
-! displacement, velocity, acceleration
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: &
-     displ_inner_core,veloc_inner_core,accel_inner_core
-
-! Newmark time scheme parameters and non-dimensionalization
-  real(kind=CUSTOM_REAL) time,deltat,deltatover2,deltatsqover2
-  double precision scale_t,scale_t_inv,scale_displ,scale_veloc
-
-! ADJOINT
-  real(kind=CUSTOM_REAL) b_deltat,b_deltatover2,b_deltatsqover2
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE_ADJOINT) :: &
-    b_displ_crust_mantle,b_veloc_crust_mantle,b_accel_crust_mantle
-  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE_ADJOINT) :: &
-    b_displ_outer_core,b_veloc_outer_core,b_accel_outer_core
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE_ADJOINT) :: &
-    b_displ_inner_core,b_veloc_inner_core,b_accel_inner_core
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: div_displ_outer_core
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: b_div_displ_outer_core
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: rho_kl_crust_mantle, &
-     beta_kl_crust_mantle, alpha_kl_crust_mantle, Sigma_kl_crust_mantle
-! For anisotropic kernels (see compute_kernels.f90 for a definition of the array)
-  real(kind=CUSTOM_REAL), dimension(21,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT) :: cijkl_kl_crust_mantle
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: rho_kl_outer_core, &
-     alpha_kl_outer_core
-
-  ! approximate hessian
-  real(kind=CUSTOM_REAL), dimension(:,:,:,:),allocatable :: hess_kl_crust_mantle
-
-  ! check for deviatoric kernel for outer core region
-  real(kind=CUSTOM_REAL), dimension(:,:,:,:),allocatable :: beta_kl_outer_core
-  integer :: nspec_beta_kl_outer_core
-  logical,parameter:: deviatoric_outercore = .false.
-
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_ADJOINT) :: rho_kl_inner_core, &
-     beta_kl_inner_core, alpha_kl_inner_core
-
-  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:), allocatable :: absorb_xmin_crust_mantle5, &
-     absorb_xmax_crust_mantle5, absorb_ymin_crust_mantle5, absorb_ymax_crust_mantle5
-
-  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: absorb_xmin_outer_core, &
-     absorb_xmax_outer_core, absorb_ymin_outer_core, absorb_ymax_outer_core, &
-     absorb_zmin_outer_core
-  integer nabs_xmin_cm,nabs_xmax_cm,nabs_ymin_cm,nabs_ymax_cm
-  integer nabs_xmin_oc,nabs_xmax_oc,nabs_ymin_oc,nabs_ymax_oc,nabs_zmin_oc
-
-  integer reclen_xmin_crust_mantle, reclen_xmax_crust_mantle, reclen_ymin_crust_mantle, &
-     reclen_ymax_crust_mantle, reclen_xmin_outer_core, reclen_xmax_outer_core,&
-     reclen_ymin_outer_core, reclen_ymax_outer_core, reclen_zmin
-
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_OUTER_CORE) :: vector_accel_outer_core,&
-             vector_displ_outer_core, b_vector_displ_outer_core
-
-  integer npoin2D_faces_crust_mantle(NUMFACES_SHARED)
-  integer npoin2D_faces_outer_core(NUMFACES_SHARED)
-  integer npoin2D_faces_inner_core(NUMFACES_SHARED)
-
-! parameters for the source
-  integer it
-  integer, dimension(:), allocatable :: islice_selected_source,ispec_selected_source
-  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:), allocatable :: sourcearrays
-  double precision, dimension(:,:,:) ,allocatable:: nu_source
-  double precision sec
-  double precision, dimension(:), allocatable :: Mxx,Myy,Mzz,Mxy,Mxz,Myz
-  double precision, dimension(:), allocatable :: xi_source,eta_source,gamma_source
-  double precision, dimension(:), allocatable :: tshift_cmt,hdur,hdur_gaussian
-  double precision, dimension(:), allocatable :: theta_source,phi_source
-  double precision, external :: comp_source_time_function
-  double precision t0
-
-! receiver information
-  integer nrec,nrec_local
-  integer, dimension(:), allocatable :: islice_selected_rec,ispec_selected_rec,number_receiver_global
-  double precision, dimension(:), allocatable :: xi_receiver,eta_receiver,gamma_receiver
-  character(len=150) :: STATIONS,rec_filename
-  double precision, dimension(:,:,:), allocatable :: nu
-  double precision, allocatable, dimension(:) :: stlat,stlon,stele,stbur
-  character(len=MAX_LENGTH_STATION_NAME), dimension(:), allocatable  :: station_name
-  character(len=MAX_LENGTH_NETWORK_NAME), dimension(:), allocatable :: network_name
-
-!ADJOINT
-  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:,:), allocatable :: adj_sourcearrays
-  integer nrec_simulation, nadj_rec_local
-  integer NSTEP_SUB_ADJ  ! to read input in chunks
-  integer, dimension(:,:), allocatable :: iadjsrc ! to read input in chunks
-  integer, dimension(:), allocatable :: iadjsrc_len,iadj_vec
-! source frechet derivatives
-  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: moment_der
-  real(kind=CUSTOM_REAL), dimension(:,:), allocatable :: sloc_der
-  real(kind=CUSTOM_REAL), dimension(:), allocatable :: stshift_der, shdur_der
-  double precision, dimension(:,:), allocatable :: hpxir_store,hpetar_store,hpgammar_store
-  integer :: nadj_hprec_local
-
-! seismograms
-  integer it_begin,it_end,nit_written
-  real(kind=CUSTOM_REAL), dimension(:,:,:), allocatable :: seismograms
-  integer :: seismo_offset, seismo_current
-
-! non-dimensionalized rotation rate of the Earth times two
-  real(kind=CUSTOM_REAL) two_omega_earth
-
-! for the Euler scheme for rotation
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ROTATION) :: &
-    A_array_rotation,B_array_rotation
-
-! number of faces between chunks
-  integer NUMMSGS_FACES
-
-! number of corners between chunks
-  integer NCORNERSCHUNKS
-
-! number of message types
-  integer NUM_MSG_TYPES
-
-! indirect addressing for each corner of the chunks
-  integer, dimension(NGLOB1D_RADIAL_CM,NUMCORNERS_SHARED) :: iboolcorner_crust_mantle
-  integer, dimension(NGLOB1D_RADIAL_OC,NUMCORNERS_SHARED) :: iboolcorner_outer_core
-  integer, dimension(NGLOB1D_RADIAL_IC,NUMCORNERS_SHARED) :: iboolcorner_inner_core
-
-! buffers for send and receive between corners of the chunks
-  real(kind=CUSTOM_REAL), dimension(NGLOB1D_RADIAL_CM) :: buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
-                                                          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar
-! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB1D_RADIAL_CM + NGLOB1D_RADIAL_IC) :: &
-     buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
-     b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector
-
-! Gauss-Lobatto-Legendre points of integration and weights
-  double precision, dimension(NGLLX) :: xigll,wxgll
-  double precision, dimension(NGLLY) :: yigll,wygll
-  double precision, dimension(NGLLZ) :: zigll,wzgll
-
-! product of weights for gravity term
-  double precision, dimension(NGLLX,NGLLY,NGLLZ) :: wgll_cube
-
-! array with derivatives of Lagrange polynomials and precalculated products
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xx,hprimewgll_xx
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLX) :: hprime_xxT,hprimewgll_xxT
-  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLY) :: hprime_yy,hprimewgll_yy
-  real(kind=CUSTOM_REAL), dimension(NGLLZ,NGLLZ) :: hprime_zz,hprimewgll_zz
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY) :: wgllwgll_xy
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLZ) :: wgllwgll_xz
-  real(kind=CUSTOM_REAL), dimension(NGLLY,NGLLZ) :: wgllwgll_yz
-
-! Lagrange interpolators at receivers
-  double precision, dimension(:,:), allocatable :: hxir_store,hetar_store,hgammar_store
-
-! 2-D addressing and buffers for summation between slices
-  integer, dimension(NGLOB2DMAX_XMIN_XMAX_CM) :: iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle
-  integer, dimension(NGLOB2DMAX_YMIN_YMAX_CM) :: iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle
-
-  integer, dimension(NGLOB2DMAX_XMIN_XMAX_OC) :: iboolleft_xi_outer_core,iboolright_xi_outer_core
-  integer, dimension(NGLOB2DMAX_YMIN_YMAX_OC) :: iboolleft_eta_outer_core,iboolright_eta_outer_core
-
-  integer, dimension(NGLOB2DMAX_XMIN_XMAX_IC) :: iboolleft_xi_inner_core,iboolright_xi_inner_core
-  integer, dimension(NGLOB2DMAX_YMIN_YMAX_IC) :: iboolleft_eta_inner_core,iboolright_eta_inner_core
-
-! for addressing of the slices
-  integer, dimension(NCHUNKS_VAL,0:NPROC_XI_VAL-1,0:NPROC_ETA_VAL-1) :: addressing
-  integer, dimension(0:NPROCTOT_VAL-1) :: ichunk_slice,iproc_xi_slice,iproc_eta_slice
-
-! proc numbers for MPI
-  integer myrank
-
-  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle
-  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_outer_core,npoin2D_eta_outer_core
-  integer, dimension(NB_SQUARE_EDGES_ONEDIR) :: npoin2D_xi_inner_core,npoin2D_eta_inner_core
-
-  integer ichunk,iproc_xi,iproc_eta
-
-!ADJOINT
-  real(kind=CUSTOM_REAL) b_two_omega_earth
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ROT_ADJOINT) :: &
-    b_A_array_rotation,b_B_array_rotation
-
-  double precision :: time_start
-
-! parameters read from parameter file
-  integer MIN_ATTENUATION_PERIOD,MAX_ATTENUATION_PERIOD,NER_CRUST, &
-          NER_80_MOHO,NER_220_80,NER_400_220,NER_600_400,NER_670_600,NER_771_670, &
-          NER_TOPDDOUBLEPRIME_771,NER_CMB_TOPDDOUBLEPRIME,NER_OUTER_CORE, &
-          NER_TOP_CENTRAL_CUBE_ICB,NEX_XI,NEX_ETA, &
-          NTSTEP_BETWEEN_OUTPUT_SEISMOS,&
-          NTSTEP_BETWEEN_READ_ADJSRC,NSTEP,NSOURCES,NTSTEP_BETWEEN_FRAMES, &
-          NTSTEP_BETWEEN_OUTPUT_INFO,NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN,SIMULATION_TYPE, &
-          MOVIE_VOLUME_TYPE,MOVIE_START,MOVIE_STOP,NOISE_TOMOGRAPHY
-
-  double precision DT,ROCEAN,RMIDDLE_CRUST, &
-          RMOHO,R80,R220,R400,R600,R670,R771,RTOPDDOUBLEPRIME,RCMB,RICB, &
-          RHO_TOP_OC,RHO_BOTTOM_OC,RHO_OCEANS,HDUR_MOVIE, &
-          MOVIE_TOP,MOVIE_BOTTOM,MOVIE_WEST,MOVIE_EAST,MOVIE_NORTH,MOVIE_SOUTH, &
-          ANGULAR_WIDTH_XI_IN_DEGREES
-
-  logical ONE_CRUST,TOPOGRAPHY,MOVIE_SURFACE,MOVIE_VOLUME,MOVIE_COARSE, &
-          RECEIVERS_CAN_BE_BURIED,PRINT_SOURCE_TIME_FUNCTION, &
-          SAVE_MESH_FILES,ABSORBING_CONDITIONS,INCLUDE_CENTRAL_CUBE,SAVE_FORWARD, &
-          OUTPUT_SEISMOS_ASCII_TEXT,OUTPUT_SEISMOS_SAC_ALPHANUM,OUTPUT_SEISMOS_SAC_BINARY, &
-          ROTATE_SEISMOGRAMS_RT,HONOR_1D_SPHERICAL_MOHO,WRITE_SEISMOGRAMS_BY_MASTER,&
-          SAVE_ALL_SEISMOS_IN_ONE_FILE,USE_BINARY_FOR_LARGE_FILE
-
-  character(len=150) OUTPUT_FILES,LOCAL_PATH
-
-!  logical COMPUTE_AND_STORE_STRAIN
-
-! for SAC headers for seismograms
-  integer yr_SAC,jda_SAC,ho_SAC,mi_SAC
-  real mb_SAC
-  double precision t_cmt_SAC,t_shift_SAC,elat_SAC,elon_SAC,depth_SAC, &
-    cmt_lat_SAC,cmt_lon_SAC,cmt_depth_SAC,cmt_hdur_SAC,sec_SAC
-  character(len=20) event_name_SAC
-
-! this for all the regions
-  integer, dimension(MAX_NUM_REGIONS) :: NSPEC2DMAX_XMIN_XMAX,NSPEC2DMAX_YMIN_YMAX, &
-               NSPEC2D_BOTTOM,NSPEC2D_TOP, &
-               NGLOB1D_RADIAL, &
-               NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX
-
-  character(len=150) prname
-
-! lookup table every km for gravity
-  real(kind=CUSTOM_REAL) minus_g_cmb,minus_g_icb
-  double precision, dimension(NRAD_GRAVITY) :: minus_gravity_table, &
-    minus_deriv_gravity_table,density_table,d_ln_density_dr_table,minus_rho_g_over_kappa_fluid
-
-! dummy array that does not need to be actually read
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,1) :: dummy_array
-
-! computed in read_compute_parameters
-  integer, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: ner,ratio_sampling_array
-  integer, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: doubling_index
-  double precision, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: r_bottom,r_top
-  logical, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: this_region_has_a_doubling
-  double precision, dimension(MAX_NUMBER_OF_MESH_LAYERS) :: rmins,rmaxs
-
-! Boundary Mesh and Kernels
-  integer k_top,k_bot,iregion_code
-  integer, dimension(NSPEC2D_MOHO) :: ibelm_moho_top,ibelm_moho_bot
-  integer, dimension(NSPEC2D_400) :: ibelm_400_top,ibelm_400_bot
-  integer, dimension(NSPEC2D_670) :: ibelm_670_top,ibelm_670_bot
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_MOHO) :: normal_moho
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_400) :: normal_400
-  real(kind=CUSTOM_REAL), dimension(NDIM,NGLLX,NGLLY,NSPEC2D_670) :: normal_670
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_MOHO) :: moho_kl, moho_kl_top, moho_kl_bot
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_400) :: d400_kl, d400_kl_top, d400_kl_bot
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_670) ::  d670_kl, d670_kl_top, d670_kl_bot
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_CMB) :: cmb_kl, cmb_kl_top, cmb_kl_bot
-  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NSPEC2D_ICB) :: icb_kl, icb_kl_top, icb_kl_bot
-  logical :: fluid_solid_boundary
-
-  integer :: i,ier
-
-  integer :: imodulo_NGLOB_CRUST_MANTLE,imodulo_NGLOB_OUTER_CORE,imodulo_NGLOB_INNER_CORE
-
-! NOISE_TOMOGRAPHY
-  real(kind=CUSTOM_REAL), dimension(:,:,:,:,:), allocatable :: noise_sourcearray
-  real(kind=CUSTOM_REAL), dimension(:), allocatable :: &
-             normal_x_noise,normal_y_noise,normal_z_noise, mask_noise
-  real(kind=CUSTOM_REAL), dimension(:,:,:,:), allocatable :: noise_surface_movie
-  integer :: irec_master_noise
-
-! ************** PROGRAM STARTS HERE **************
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-! trivia about the programming style adopted here:
-!
-! note 1: for performance reasons, we try to use as much from the stack memory as possible.
-!             This is done to avoid memory fragmentation and also to optimize performance.
-!             Stack memory is a place in computer memory where all the variables that are declared
-!             and initialized **before** runtime are stored. Our static array allocation will use that one.
-!             All variables declared within our main routine also will be stored on the stack.
-!
-!             the heap is the section of computer memory where all the variables created or initialized
-!             **at** runtime are stored. it is used for dynamic memory allocation.
-!
-!             stack is much faster than the heap.
-!
-!             when calling a function, additional storage will be allocated for the variables in that function.
-!             that storage will be allocated in the heap memory segment.
-!
-!             most routine calls here will have rather long argument lists, probably because of this performance criteria.
-!             using modules/common data blocks together with dynamic allocation will put data into heap memory,
-!             thus it has longer latency to access variables than stack memory variables.
-!
-!             however, declaring the static arrays needed in compute_forces_crust_mantle_Dev()
-!             like e.g. sum_terms, tempx1,...B1_m1_m2_5points,... in this main routine and
-!             passing them along as arguments to the routine makes the code slower.
-!             it seems that this stack/heap criterion is more complicated.
-!
-!             another reason why modules are avoided is to make the code thread safe.
-!             having different threads access the same data structure and modifying it at the same time
-!             would lead to problems. passing arguments is a way to avoid such complications.
-!
-! note 2: Most of the computation time is spent
-!             inside the time loop (mainly in the compute_forces_crust_mantle_Dev() routine).
-!             Any code performance tuning will be most effective in there.
-!
-! note 3: Fortran is a code language that uses column-first ordering for arrays,
-!             e.g., it stores a(i,j) in this order: a(1,1),a(2,1),a(3,1),...,a(1,2),a(2,2),a(3,2),..
-!             it is therefore more efficient to have the inner-loop over i, and the outer loop over j
-!
-! note 4: Deville et al. (2002) routines significantly reduce the total number of memory accesses
-!             required to perform matrix-matrix products at the spectral element level.
-!             For most compilers and hardware, will result in a significant speedup (> 30% or more, sometimes twice faster).
-!
-! note 5: a common technique to help compilers enhance pipelining is loop unrolling. We do this here in a simple
-!             and straigthforward way, so don't be confused about the do-loop writing.
-!
-! note 6: whenever adding some new code, please make sure to use
-!             spaces rather than tabs. Tabulators are in principle not allowed in Fortran95.
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-  ! initialize the MPI communicator and start the NPROCTOT MPI processes.
-  call MPI_INIT(ier)
-
-  ! force Flush-To-Zero if available to avoid very slow Gradual Underflow trapping
-  call force_ftz()
-
-  ! initializes simulation parameters
-  call initialize_simulation(myrank,MIN_ATTENUATION_PERIOD,MAX_ATTENUATION_PERIOD,NER_CRUST, &
-                NER_80_MOHO,NER_220_80,NER_400_220,NER_600_400,NER_670_600,NER_771_670, &
-                NER_TOPDDOUBLEPRIME_771,NER_CMB_TOPDDOUBLEPRIME,NER_OUTER_CORE, &
-                NER_TOP_CENTRAL_CUBE_ICB,ANGULAR_WIDTH_XI_IN_DEGREES,NEX_XI,NEX_ETA, &
-                NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
-                NTSTEP_BETWEEN_READ_ADJSRC,NSTEP,NSOURCES,NTSTEP_BETWEEN_FRAMES, &
-                NTSTEP_BETWEEN_OUTPUT_INFO,NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN,SIMULATION_TYPE, &
-                DT,ROCEAN,RMIDDLE_CRUST,RMOHO,R80,R220,R400,R600,R670,R771,&
-                RTOPDDOUBLEPRIME,RCMB,RICB, &
-                RHO_TOP_OC,RHO_BOTTOM_OC,RHO_OCEANS, &
-                MOVIE_VOLUME_TYPE,MOVIE_START,MOVIE_STOP, &
-                HDUR_MOVIE,MOVIE_TOP,MOVIE_BOTTOM,MOVIE_WEST,MOVIE_EAST, &
-                MOVIE_NORTH,MOVIE_SOUTH,MOVIE_SURFACE,MOVIE_VOLUME, &
-                RECEIVERS_CAN_BE_BURIED,PRINT_SOURCE_TIME_FUNCTION, &
-                SAVE_MESH_FILES,ABSORBING_CONDITIONS,INCLUDE_CENTRAL_CUBE,SAVE_FORWARD, &
-                SAVE_ALL_SEISMOS_IN_ONE_FILE,MOVIE_COARSE,OUTPUT_SEISMOS_ASCII_TEXT, &
-                OUTPUT_SEISMOS_SAC_ALPHANUM,OUTPUT_SEISMOS_SAC_BINARY, &
-                ROTATE_SEISMOGRAMS_RT,WRITE_SEISMOGRAMS_BY_MASTER,USE_BINARY_FOR_LARGE_FILE, &
-                LOCAL_PATH,OUTPUT_FILES, &
-                ratio_sampling_array, ner, doubling_index,r_bottom,r_top, &
-                this_region_has_a_doubling,rmins,rmaxs, &
-                TOPOGRAPHY,HONOR_1D_SPHERICAL_MOHO,ONE_CRUST, &
-                nspl,rspl,espl,espl2,ibathy_topo, &
-                NSPEC2DMAX_XMIN_XMAX,NSPEC2DMAX_YMIN_YMAX,NSPEC2D_BOTTOM,NSPEC2D_TOP, &
-                NGLOB1D_RADIAL,NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX, &
-                xigll,yigll,zigll,wxgll,wygll,wzgll,wgll_cube, &
-                hprime_xx,hprime_yy,hprime_zz,hprime_xxT, &
-                hprimewgll_xx,hprimewgll_yy,hprimewgll_zz,hprimewgll_xxT, &
-                wgllwgll_xy,wgllwgll_xz,wgllwgll_yz, &
-                rec_filename,STATIONS,nrec,NOISE_TOMOGRAPHY)
-
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-! starts reading the databases
-  call read_mesh_databases(myrank,rho_vp_crust_mantle,rho_vs_crust_mantle, &
-              xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-              xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-              etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-              gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-              rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
-              kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-              nspec_iso,nspec_tiso,nspec_ani, &
-              c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-              c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-              c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-              c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-              c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-              c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-              c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-              ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-            ! -- idoubling_crust_mantle,
-              is_on_a_slice_edge_crust_mantle,rmass_crust_mantle,rmass_ocean_load, &
-              vp_outer_core,xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-              xix_outer_core,xiy_outer_core,xiz_outer_core, &
-              etax_outer_core,etay_outer_core,etaz_outer_core, &
-              gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-              rhostore_outer_core,kappavstore_outer_core, &
-              ibool_outer_core,idoubling_outer_core,ispec_is_tiso_outer_core, &
-              is_on_a_slice_edge_outer_core,rmass_outer_core, &
-              xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-              xix_inner_core,xiy_inner_core,xiz_inner_core, &
-              etax_inner_core,etay_inner_core,etaz_inner_core, &
-              gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-              rhostore_inner_core,kappavstore_inner_core,muvstore_inner_core, &
-              c11store_inner_core,c12store_inner_core,c13store_inner_core, &
-              c33store_inner_core,c44store_inner_core, &
-              ibool_inner_core,idoubling_inner_core,ispec_is_tiso_inner_core, &
-              is_on_a_slice_edge_inner_core,rmass_inner_core, &
-              ABSORBING_CONDITIONS,LOCAL_PATH)
-
-  ! read 2-D addressing for summation between slices with MPI
-  call read_mesh_databases_addressing(myrank, &
-              iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
-              iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-              npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-              iboolfaces_crust_mantle,npoin2D_faces_crust_mantle, &
-              iboolcorner_crust_mantle, &
-              iboolleft_xi_outer_core,iboolright_xi_outer_core, &
-              iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-              npoin2D_xi_outer_core,npoin2D_eta_outer_core,&
-              iboolfaces_outer_core,npoin2D_faces_outer_core, &
-              iboolcorner_outer_core, &
-              iboolleft_xi_inner_core,iboolright_xi_inner_core, &
-              iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-              npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-              iboolfaces_inner_core,npoin2D_faces_inner_core, &
-              iboolcorner_inner_core, &
-              iprocfrom_faces,iprocto_faces,imsg_type, &
-              iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-              LOCAL_PATH,OUTPUT_FILES, &
-              NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX,NGLOB1D_RADIAL, &
-              NGLOB2DMAX_XY,NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
-              addressing,ichunk_slice,iproc_xi_slice,iproc_eta_slice, &
-              ichunk,iproc_xi,iproc_eta)
-
-  ! to couple mantle with outer core
-  call read_mesh_databases_coupling(myrank, &
-              nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle, &
-              nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle, &
-              ibelm_xmin_crust_mantle,ibelm_xmax_crust_mantle,ibelm_ymin_crust_mantle, &
-              ibelm_ymax_crust_mantle,ibelm_bottom_crust_mantle,ibelm_top_crust_mantle, &
-              normal_xmin_crust_mantle,normal_xmax_crust_mantle,normal_ymin_crust_mantle, &
-              normal_ymax_crust_mantle,normal_bottom_crust_mantle,normal_top_crust_mantle, &
-              jacobian2D_xmin_crust_mantle,jacobian2D_xmax_crust_mantle,jacobian2D_ymin_crust_mantle, &
-              jacobian2D_ymax_crust_mantle,jacobian2D_bottom_crust_mantle,jacobian2D_top_crust_mantle, &
-              nspec2D_xmin_outer_core,nspec2D_xmax_outer_core, &
-              nspec2D_ymin_outer_core,nspec2D_ymax_outer_core, &
-              ibelm_xmin_outer_core,ibelm_xmax_outer_core,ibelm_ymin_outer_core, &
-              ibelm_ymax_outer_core,ibelm_bottom_outer_core,ibelm_top_outer_core, &
-              normal_xmin_outer_core,normal_xmax_outer_core,normal_ymin_outer_core, &
-              normal_ymax_outer_core,normal_bottom_outer_core,normal_top_outer_core, &
-              jacobian2D_xmin_outer_core,jacobian2D_xmax_outer_core,jacobian2D_ymin_outer_core, &
-              jacobian2D_ymax_outer_core,jacobian2D_bottom_outer_core,jacobian2D_top_outer_core, &
-              nspec2D_xmin_inner_core,nspec2D_xmax_inner_core, &
-              nspec2D_ymin_inner_core,nspec2D_ymax_inner_core, &
-              ibelm_xmin_inner_core,ibelm_xmax_inner_core,ibelm_ymin_inner_core, &
-              ibelm_ymax_inner_core,ibelm_bottom_inner_core,ibelm_top_inner_core, &
-              ibelm_moho_top,ibelm_moho_bot,ibelm_400_top,ibelm_400_bot, &
-              ibelm_670_top,ibelm_670_bot,normal_moho,normal_400,normal_670, &
-              k_top,k_bot,moho_kl,d400_kl,d670_kl,cmb_kl,icb_kl, &
-              LOCAL_PATH,SIMULATION_TYPE)
-
-! added this to reduce the size of the buffers
-! size of buffers is the sum of two sizes because we handle two regions in the same MPI call
-  npoin2D_max_all_CM_IC = max(maxval(npoin2D_xi_crust_mantle(:) + npoin2D_xi_inner_core(:)), &
-                        maxval(npoin2D_eta_crust_mantle(:) + npoin2D_eta_inner_core(:)))
-
-  allocate(buffer_send_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED), &
-          buffer_received_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED),stat=ier)
-  if( ier /= 0 ) call exit_MPI(myrank,'error allocating mpi buffer')
-
-  allocate(b_buffer_send_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED), &
-          b_buffer_received_faces(NDIM,npoin2D_max_all_CM_IC,NUMFACES_SHARED),stat=ier)
-  if( ier /= 0 ) call exit_MPI(myrank,'error allocating mpi b_buffer')
-
-  call fix_non_blocking_slices(is_on_a_slice_edge_crust_mantle,iboolright_xi_crust_mantle, &
-         iboolleft_xi_crust_mantle,iboolright_eta_crust_mantle,iboolleft_eta_crust_mantle, &
-         npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle,ibool_crust_mantle, &
-         mask_ibool,NSPEC_CRUST_MANTLE,NGLOB_CRUST_MANTLE,NGLOB2DMAX_XMIN_XMAX_CM,NGLOB2DMAX_YMIN_YMAX_CM)
-
-  call fix_non_blocking_slices(is_on_a_slice_edge_outer_core,iboolright_xi_outer_core, &
-         iboolleft_xi_outer_core,iboolright_eta_outer_core,iboolleft_eta_outer_core, &
-         npoin2D_xi_outer_core,npoin2D_eta_outer_core,ibool_outer_core, &
-         mask_ibool,NSPEC_OUTER_CORE,NGLOB_OUTER_CORE,NGLOB2DMAX_XMIN_XMAX_OC,NGLOB2DMAX_YMIN_YMAX_OC)
-
-  call fix_non_blocking_slices(is_on_a_slice_edge_inner_core,iboolright_xi_inner_core, &
-         iboolleft_xi_inner_core,iboolright_eta_inner_core,iboolleft_eta_inner_core, &
-         npoin2D_xi_inner_core,npoin2D_eta_inner_core,ibool_inner_core, &
-         mask_ibool,NSPEC_INNER_CORE,NGLOB_INNER_CORE,NGLOB2DMAX_XMIN_XMAX_IC,NGLOB2DMAX_YMIN_YMAX_IC)
-
-  ! absorbing boundaries
-  if(ABSORBING_CONDITIONS) then
-    ! crust_mantle
-    if (nspec2D_xmin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_xmin_cm = nspec2D_xmin_crust_mantle
-    else
-      nabs_xmin_cm = 1
-    endif
-    allocate(absorb_xmin_crust_mantle5(NDIM,NGLLY,NGLLZ,nabs_xmin_cm,8),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmin')
-
-    if (nspec2D_xmax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_xmax_cm = nspec2D_xmax_crust_mantle
-    else
-      nabs_xmax_cm = 1
-    endif
-    allocate(absorb_xmax_crust_mantle5(NDIM,NGLLY,NGLLZ,nabs_xmax_cm,8),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmax')
-
-    if (nspec2D_ymin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_ymin_cm = nspec2D_ymin_crust_mantle
-    else
-      nabs_ymin_cm = 1
-    endif
-    allocate(absorb_ymin_crust_mantle5(NDIM,NGLLX,NGLLZ,nabs_ymin_cm,8),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymin')
-
-    if (nspec2D_ymax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_ymax_cm = nspec2D_ymax_crust_mantle
-    else
-      nabs_ymax_cm = 1
-    endif
-    allocate(absorb_ymax_crust_mantle5(NDIM,NGLLX,NGLLZ,nabs_ymax_cm,8),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymax')
-
-    ! outer_core
-    if (nspec2D_xmin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_xmin_oc = nspec2D_xmin_outer_core
-    else
-      nabs_xmin_oc = 1
-    endif
-    allocate(absorb_xmin_outer_core(NGLLY,NGLLZ,nabs_xmin_oc),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmin')
-
-    if (nspec2D_xmax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_xmax_oc = nspec2D_xmax_outer_core
-    else
-      nabs_xmax_oc = 1
-    endif
-    allocate(absorb_xmax_outer_core(NGLLY,NGLLZ,nabs_xmax_oc),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb xmax')
-
-    if (nspec2D_ymin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_ymin_oc = nspec2D_ymin_outer_core
-    else
-      nabs_ymin_oc = 1
-    endif
-    allocate(absorb_ymin_outer_core(NGLLX,NGLLZ,nabs_ymin_oc),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymin')
-
-    if (nspec2D_ymax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_ymax_oc = nspec2D_ymax_outer_core
-    else
-      nabs_ymax_oc = 1
-    endif
-    allocate(absorb_ymax_outer_core(NGLLX,NGLLZ,nabs_ymax_oc),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb ymax')
-
-    if (NSPEC2D_BOTTOM(IREGION_OUTER_CORE) > 0 .and. &
-       (SIMULATION_TYPE == 3 .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      nabs_zmin_oc = NSPEC2D_BOTTOM(IREGION_OUTER_CORE)
-    else
-      nabs_zmin_oc = 1
-    endif
-    allocate(absorb_zmin_outer_core(NGLLX,NGLLY,nabs_zmin_oc),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating absorb zmin')
-
-    ! read arrays for Stacey conditions
-    call read_mesh_databases_stacey(myrank, &
-                      nimin_crust_mantle,nimax_crust_mantle,njmin_crust_mantle, &
-                      njmax_crust_mantle,nkmin_xi_crust_mantle,nkmin_eta_crust_mantle, &
-                      nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle, &
-                      nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle, &
-                      reclen_xmin_crust_mantle,reclen_xmax_crust_mantle, &
-                      reclen_ymin_crust_mantle,reclen_ymax_crust_mantle, &
-                      nimin_outer_core,nimax_outer_core,njmin_outer_core, &
-                      njmax_outer_core,nkmin_xi_outer_core,nkmin_eta_outer_core, &
-                      nspec2D_xmin_outer_core,nspec2D_xmax_outer_core, &
-                      nspec2D_ymin_outer_core,nspec2D_ymax_outer_core, &
-                      reclen_xmin_outer_core,reclen_xmax_outer_core, &
-                      reclen_ymin_outer_core,reclen_ymax_outer_core, &
-                      reclen_zmin,NSPEC2D_BOTTOM, &
-                      SIMULATION_TYPE,SAVE_FORWARD,LOCAL_PATH,NSTEP)
-
-  endif
-
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-! source and receivers
-
-  ! allocate arrays for source
-  allocate(islice_selected_source(NSOURCES), &
-          ispec_selected_source(NSOURCES), &
-          Mxx(NSOURCES), &
-          Myy(NSOURCES), &
-          Mzz(NSOURCES), &
-          Mxy(NSOURCES), &
-          Mxz(NSOURCES), &
-          Myz(NSOURCES), &
-          xi_source(NSOURCES), &
-          eta_source(NSOURCES), &
-          gamma_source(NSOURCES), &
-          tshift_cmt(NSOURCES), &
-          hdur(NSOURCES), &
-          hdur_gaussian(NSOURCES), &
-          theta_source(NSOURCES), &
-          phi_source(NSOURCES), &
-          nu_source(NDIM,NDIM,NSOURCES),stat=ier)
-  if( ier /= 0 ) call exit_MPI(myrank,'error allocating source arrays')
-
-  ! allocate memory for receiver arrays
-  allocate(islice_selected_rec(nrec), &
-          ispec_selected_rec(nrec), &
-          xi_receiver(nrec), &
-          eta_receiver(nrec), &
-          gamma_receiver(nrec), &
-          station_name(nrec), &
-          network_name(nrec), &
-          stlat(nrec), &
-          stlon(nrec), &
-          stele(nrec), &
-          stbur(nrec), &
-          nu(NDIM,NDIM,nrec),stat=ier)
-  if( ier /= 0 ) call exit_MPI(myrank,'error allocating receiver arrays')
-
-  ! locates sources and receivers
-  call setup_sources_receivers(NSOURCES,myrank,ibool_crust_mantle, &
-                      xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-                      xigll,yigll,zigll,TOPOGRAPHY, &
-                      sec,tshift_cmt,theta_source,phi_source, &
-                      NSTEP,DT,hdur,hdur_gaussian,t0,Mxx,Myy,Mzz,Mxy,Mxz,Myz, &
-                      islice_selected_source,ispec_selected_source, &
-                      xi_source,eta_source,gamma_source,nu_source, &
-                      rspl,espl,espl2,nspl,ibathy_topo,NEX_XI,PRINT_SOURCE_TIME_FUNCTION, &
-                      rec_filename,nrec,islice_selected_rec,ispec_selected_rec, &
-                      xi_receiver,eta_receiver,gamma_receiver,station_name,network_name, &
-                      stlat,stlon,stele,stbur,nu, &
-                      nrec_local,nadj_rec_local,nrec_simulation, &
-                      SIMULATION_TYPE,RECEIVERS_CAN_BE_BURIED,MOVIE_SURFACE,MOVIE_VOLUME, &
-                      HDUR_MOVIE,OUTPUT_FILES,LOCAL_PATH)
-
-  ! allocates source arrays
-  if (SIMULATION_TYPE == 1  .or. SIMULATION_TYPE == 3) then
-    allocate(sourcearrays(NDIM,NGLLX,NGLLY,NGLLZ,NSOURCES),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating sourcearrays')
-
-    ! stores source arrays
-    call setup_sources_receivers_srcarr(NSOURCES,myrank, &
-                      ispec_selected_source,islice_selected_source, &
-                      xi_source,eta_source,gamma_source, &
-                      Mxx,Myy,Mzz,Mxy,Mxz,Myz, &
-                      xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                      etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-                      gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-                      xigll,yigll,zigll,sourcearrays)
-  endif
-
-
-  if (SIMULATION_TYPE == 2 .or. SIMULATION_TYPE == 3) then
-    NSTEP_SUB_ADJ = ceiling( dble(NSTEP)/dble(NTSTEP_BETWEEN_READ_ADJSRC) )
-    allocate(iadj_vec(NSTEP),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating iadj_vec')
-
-    ! initializes iadj_vec
-    do it=1,NSTEP
-       iadj_vec(it) = NSTEP-it+1  ! default is for reversing entire record
-    enddo
-
-    if(nadj_rec_local > 0) then
-      ! allocate adjoint source arrays
-      allocate(adj_sourcearrays(NDIM,NGLLX,NGLLY,NGLLZ,nadj_rec_local,NTSTEP_BETWEEN_READ_ADJSRC),stat=ier)
-      if( ier /= 0 ) call exit_MPI(myrank,'error allocating adjoint sourcearrays')
-      adj_sourcearrays = 0._CUSTOM_REAL
-
-      ! allocate indexing arrays
-      allocate(iadjsrc(NSTEP_SUB_ADJ,2), &
-              iadjsrc_len(NSTEP_SUB_ADJ),stat=ier)
-      if( ier /= 0 ) call exit_MPI(myrank,'error allocating adjoint indexing arrays')
-      ! initializes iadjsrc, iadjsrc_len and iadj_vec
-      call setup_sources_receivers_adjindx(NSTEP,NSTEP_SUB_ADJ, &
-                      NTSTEP_BETWEEN_READ_ADJSRC, &
-                      iadjsrc,iadjsrc_len,iadj_vec)
-    endif
-  endif
-
-  ! allocates receiver interpolators
-  if (nrec_local > 0) then
-    ! allocate Lagrange interpolators for receivers
-    allocate(hxir_store(nrec_local,NGLLX), &
-            hetar_store(nrec_local,NGLLY), &
-            hgammar_store(nrec_local,NGLLZ),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating receiver interpolators')
-    ! define local to global receiver numbering mapping
-    allocate(number_receiver_global(nrec_local),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating global receiver numbering')
-    ! define and store Lagrange interpolators at all the receivers
-    if (SIMULATION_TYPE == 2) then
-      nadj_hprec_local = nrec_local
-    else
-      nadj_hprec_local = 1
-    endif
-    allocate(hpxir_store(nadj_hprec_local,NGLLX), &
-            hpetar_store(nadj_hprec_local,NGLLY), &
-            hpgammar_store(nadj_hprec_local,NGLLZ),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating derivative interpolators')
-
-    ! stores interpolators for receiver positions
-    call setup_sources_receivers_intp(NSOURCES,myrank, &
-                      islice_selected_source, &
-                      xi_source,eta_source,gamma_source, &
-                      xigll,yigll,zigll, &
-                      SIMULATION_TYPE,nrec,nrec_local, &
-                      islice_selected_rec,number_receiver_global, &
-                      xi_receiver,eta_receiver,gamma_receiver, &
-                      hxir_store,hetar_store,hgammar_store, &
-                      nadj_hprec_local,hpxir_store,hpetar_store,hpgammar_store)
-
-    ! allocate seismogram array
-    if (SIMULATION_TYPE == 1 .or. SIMULATION_TYPE == 3) then
-      allocate(seismograms(NDIM,nrec_local,NTSTEP_BETWEEN_OUTPUT_SEISMOS),stat=ier)
-      if(ier /= 0) stop 'error while allocating seismograms'
-    else
-      allocate(seismograms(NDIM*NDIM,nrec_local,NTSTEP_BETWEEN_OUTPUT_SEISMOS),stat=ier)
-      if(ier /= 0) stop 'error while allocating seismograms'
-      ! allocate Frechet derivatives array
-      allocate(moment_der(NDIM,NDIM,nrec_local),sloc_der(NDIM,nrec_local), &
-              stshift_der(nrec_local),shdur_der(nrec_local),stat=ier)
-      if( ier /= 0 ) call exit_MPI(myrank,'error allocating frechet derivatives arrays')
-
-      moment_der = 0._CUSTOM_REAL
-      sloc_der = 0._CUSTOM_REAL
-      stshift_der = 0._CUSTOM_REAL
-      shdur_der = 0._CUSTOM_REAL
-
-    endif
-    ! initialize seismograms
-    seismograms(:,:,:) = 0._CUSTOM_REAL
-    nit_written = 0
-  else
-    ! allocate dummy array since we need it to pass as argument e.g. in write_seismograms() routine
-    ! note: nrec_local is zero, fortran 90/95 should allow zero-sized array allocation...
-    allocate(seismograms(NDIM,nrec_local,NTSTEP_BETWEEN_OUTPUT_SEISMOS),stat=ier)
-    if( ier /= 0) stop 'error while allocating zero seismograms'
-    allocate(number_receiver_global(nrec_local),stat=ier)
-    if( ier /= 0) stop 'error while allocating zero number_receiver_global'
-  endif
-
-  ! get information about event name and location for SAC seismograms
-
-  ! The following line is added for get_event_info subroutine.
-  ! Because the way NSOURCES_SAC was declared has been changed.
-  ! The rest of the changes in this program is just the updates of the subroutines that
-  ! I did changes, e.g., adding/removing parameters. by Ebru Bozdag
-  call get_event_info_parallel(myrank,yr_SAC,jda_SAC,ho_SAC,mi_SAC,sec_SAC,&
-                              event_name_SAC,t_cmt_SAC,t_shift_SAC, &
-                              elat_SAC,elon_SAC,depth_SAC,mb_SAC,cmt_lat_SAC,&
-                              cmt_lon_SAC,cmt_depth_SAC,cmt_hdur_SAC,NSOURCES)
-
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-
-  ! user output
-  if(myrank == 0) then
-
-    write(IMAIN,*)
-    write(IMAIN,*) 'Reference radius of the Earth used is ',R_EARTH_KM,' km'
-    write(IMAIN,*)
-
-    write(IMAIN,*)
-    if(OCEANS_VAL) then
-      write(IMAIN,*) 'incorporating the oceans using equivalent load'
-    else
-      write(IMAIN,*) 'no oceans'
-    endif
-
-    write(IMAIN,*)
-    if(ELLIPTICITY_VAL) then
-      write(IMAIN,*) 'incorporating ellipticity'
-    else
-      write(IMAIN,*) 'no ellipticity'
-    endif
-
-    write(IMAIN,*)
-    if(TOPOGRAPHY) then
-      write(IMAIN,*) 'incorporating surface topography'
-    else
-      write(IMAIN,*) 'no surface topography'
-    endif
-
-    write(IMAIN,*)
-    if(GRAVITY_VAL) then
-      write(IMAIN,*) 'incorporating self-gravitation (Cowling approximation)'
-    else
-      write(IMAIN,*) 'no self-gravitation'
-    endif
-
-    write(IMAIN,*)
-    if(ROTATION_VAL) then
-      write(IMAIN,*) 'incorporating rotation'
-    else
-      write(IMAIN,*) 'no rotation'
-    endif
-
-    write(IMAIN,*)
-    if(ATTENUATION_VAL) then
-      write(IMAIN,*) 'incorporating attenuation using ',N_SLS,' standard linear solids'
-
-      if(ATTENUATION_3D_VAL) write(IMAIN,*) 'using 3D attenuation'
-
-      if(USE_ATTENUATION_MIMIC ) write(IMAIN,*) 'mimicking effects on velocity only'
-    else
-      write(IMAIN,*) 'no attenuation'
-    endif
-
-    write(IMAIN,*)
-    write(IMAIN,*)
-    write(IMAIN,*)
-
-  endif
-
-  ! the mass matrix needs to be assembled with MPI here once and for all
-  call prepare_timerun_rmass(myrank,rmass_ocean_load,rmass_crust_mantle, &
-                      rmass_outer_core,rmass_inner_core, &
-                      iproc_xi,iproc_eta,ichunk,addressing, &
-                      iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
-                      iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-                      npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-                      iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-                      iboolleft_xi_outer_core,iboolright_xi_outer_core, &
-                      iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-                      npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-                      iboolfaces_outer_core,iboolcorner_outer_core, &
-                      iboolleft_xi_inner_core,iboolright_xi_inner_core, &
-                      iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-                      npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-                      iboolfaces_inner_core,iboolcorner_inner_core, &
-                      iprocfrom_faces,iprocto_faces,imsg_type, &
-                      iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-                      buffer_send_faces,buffer_received_faces, &
-                      buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
-                      NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
-                      NGLOB1D_RADIAL,NGLOB2DMAX_XMIN_XMAX,NGLOB2DMAX_YMIN_YMAX,NGLOB2DMAX_XY,npoin2D_max_all_CM_IC)
-
-  ! mass matrix including central cube
-  if(INCLUDE_CENTRAL_CUBE) then
-
-    if(myrank == 0) write(IMAIN,*) 'including central cube'
-
-    ! compute number of messages to expect in cube as well as their size
-    call comp_central_cube_buffer_size(iproc_xi,iproc_eta,ichunk, &
-                NPROC_XI_VAL,NPROC_ETA_VAL,NSPEC2D_BOTTOM(IREGION_INNER_CORE), &
-                nb_msgs_theor_in_cube,npoin2D_cube_from_slices)
-
-    ! this value is used for dynamic memory allocation, therefore make sure it is never zero
-    if(nb_msgs_theor_in_cube > 0) then
-      non_zero_nb_msgs_theor_in_cube = nb_msgs_theor_in_cube
-    else
-      non_zero_nb_msgs_theor_in_cube = 1
-    endif
-
-    ! allocate buffers for cube and slices
-    allocate(sender_from_slices_to_cube(non_zero_nb_msgs_theor_in_cube), &
-            buffer_all_cube_from_slices(non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices,NDIM), &
-            b_buffer_all_cube_from_slices(non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices,NDIM), &
-            buffer_slices(npoin2D_cube_from_slices,NDIM), &
-            b_buffer_slices(npoin2D_cube_from_slices,NDIM), &
-            buffer_slices2(npoin2D_cube_from_slices,NDIM), &
-            ibool_central_cube(non_zero_nb_msgs_theor_in_cube,npoin2D_cube_from_slices),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating cube buffers')
-
-    ! handles the communications with the central cube if it was included in the mesh
-    call prepare_timerun_centralcube(myrank,rmass_inner_core, &
-                      iproc_xi,iproc_eta,ichunk, &
-                      NSPEC2DMAX_XMIN_XMAX,NSPEC2DMAX_YMIN_YMAX,NSPEC2D_BOTTOM, &
-                      addressing,ibool_inner_core,idoubling_inner_core, &
-                      xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-                      nspec2D_xmin_inner_core,nspec2D_xmax_inner_core, &
-                      nspec2D_ymin_inner_core,nspec2D_ymax_inner_core, &
-                      ibelm_xmin_inner_core,ibelm_xmax_inner_core, &
-                      ibelm_ymin_inner_core,ibelm_ymax_inner_core,ibelm_bottom_inner_core, &
-                      nb_msgs_theor_in_cube,non_zero_nb_msgs_theor_in_cube, &
-                      npoin2D_cube_from_slices,receiver_cube_from_slices, &
-                      sender_from_slices_to_cube,ibool_central_cube, &
-                      buffer_slices,buffer_slices2,buffer_all_cube_from_slices)
-
-    call fix_non_blocking_central_cube(is_on_a_slice_edge_inner_core, &
-         ibool_inner_core,NSPEC_INNER_CORE,NGLOB_INNER_CORE,nb_msgs_theor_in_cube,ibelm_bottom_inner_core, &
-         idoubling_inner_core,npoin2D_cube_from_slices,ibool_central_cube, &
-         NSPEC2D_BOTTOM(IREGION_INNER_CORE),ichunk)
-
-  else
-
-    ! allocate fictitious buffers for cube and slices with a dummy size
-    ! just to be able to use them as arguments in subroutine calls
-    allocate(sender_from_slices_to_cube(1), &
-            buffer_all_cube_from_slices(1,1,1), &
-            b_buffer_all_cube_from_slices(1,1,1), &
-            buffer_slices(1,1), &
-            b_buffer_slices(1,1), &
-            buffer_slices2(1,1), &
-            ibool_central_cube(1,1),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating dummy buffers')
-
-  endif
-
-  ! check that all the mass matrices are positive
-  if(OCEANS_VAL) then
-    if(minval(rmass_ocean_load) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the oceans')
-  endif
-  if(minval(rmass_crust_mantle) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the crust_mantle')
-  if(minval(rmass_inner_core) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the inner core')
-  if(minval(rmass_outer_core) <= 0.) call exit_MPI(myrank,'negative mass matrix term for the outer core')
-
-  ! for efficiency, invert final mass matrix once and for all on each slice
-  if(OCEANS_VAL) rmass_ocean_load = 1._CUSTOM_REAL / rmass_ocean_load
-  rmass_crust_mantle = 1._CUSTOM_REAL / rmass_crust_mantle
-  rmass_outer_core = 1._CUSTOM_REAL / rmass_outer_core
-  rmass_inner_core = 1._CUSTOM_REAL / rmass_inner_core
-
-
-  ! change x, y, z to r, theta and phi once and for all
-  ! IMPROVE dangerous: old name kept (xstore ystore zstore) for new values
-
-  ! convert in the crust and mantle
-  do i = 1,NGLOB_CRUST_MANTLE
-    call xyz_2_rthetaphi(xstore_crust_mantle(i), &
-                        ystore_crust_mantle(i), &
-                        zstore_crust_mantle(i),rval,thetaval,phival)
-    xstore_crust_mantle(i) = rval
-    ystore_crust_mantle(i) = thetaval
-    zstore_crust_mantle(i) = phival
-  enddo
-
-  ! convert in the outer core
-  do i = 1,NGLOB_OUTER_CORE
-    call xyz_2_rthetaphi(xstore_outer_core(i), &
-                        ystore_outer_core(i), &
-                        zstore_outer_core(i),rval,thetaval,phival)
-    xstore_outer_core(i) = rval
-    ystore_outer_core(i) = thetaval
-    zstore_outer_core(i) = phival
-  enddo
-
-  ! convert in the inner core
-  do i = 1,NGLOB_INNER_CORE
-    call xyz_2_rthetaphi(xstore_inner_core(i), &
-                        ystore_inner_core(i), &
-                        zstore_inner_core(i),rval,thetaval,phival)
-    xstore_inner_core(i) = rval
-    ystore_inner_core(i) = thetaval
-    zstore_inner_core(i) = phival
-  enddo
-
-  ! allocate files to save movies
-  if(MOVIE_SURFACE .or. NOISE_TOMOGRAPHY /=0) then    ! for noise tomography, store_val_x/y/z/ux/uy/uz needed for 'surface movie'
-    if(MOVIE_COARSE .and. NOISE_TOMOGRAPHY ==0) then  ! only output corners !for noise tomography, must NOT be coarse
-       nmovie_points = 2 * 2 * NSPEC2D_TOP(IREGION_CRUST_MANTLE)
-       if(NGLLX /= NGLLY) &
-        call exit_MPI(myrank,'MOVIE_COARSE together with MOVIE_SURFACE requires NGLLX=NGLLY')
-       NIT = NGLLX - 1
-    else
-       nmovie_points = NGLLX * NGLLY * NSPEC2D_TOP(IREGION_CRUST_MANTLE)
-       NIT = 1
-    endif
-    allocate(store_val_x(nmovie_points), &
-            store_val_y(nmovie_points), &
-            store_val_z(nmovie_points), &
-            store_val_ux(nmovie_points), &
-            store_val_uy(nmovie_points), &
-            store_val_uz(nmovie_points),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating movie surface arrays')
-
-    if (MOVIE_SURFACE) then  ! those arrays are not neccessary for noise tomography, so only allocate them in MOVIE_SURFACE case
-       allocate(store_val_x_all(nmovie_points,0:NPROCTOT_VAL-1), &
-              store_val_y_all(nmovie_points,0:NPROCTOT_VAL-1), &
-              store_val_z_all(nmovie_points,0:NPROCTOT_VAL-1), &
-              store_val_ux_all(nmovie_points,0:NPROCTOT_VAL-1), &
-              store_val_uy_all(nmovie_points,0:NPROCTOT_VAL-1), &
-              store_val_uz_all(nmovie_points,0:NPROCTOT_VAL-1),stat=ier)
-       if( ier /= 0 ) call exit_MPI(myrank,'error allocating movie surface all arrays')
-    endif
-    if(myrank == 0) then
-      write(IMAIN,*)
-      write(IMAIN,*) 'Movie surface:'
-      write(IMAIN,*) '  Writing to moviedata*** files in output directory'
-      if(MOVIE_VOLUME_TYPE == 5) then
-        write(IMAIN,*) '  movie output: displacement'
-      else
-        write(IMAIN,*) '  movie output: velocity'
-      endif
-      write(IMAIN,*) '  time steps every: ',NTSTEP_BETWEEN_FRAMES
-    endif
-  endif
-
-
-  ! output point and element information for 3D movies
-  if(MOVIE_VOLUME) then
-    ! the following has to be true for the the array dimensions of eps to match with those of xstore etc..
-    ! note that epsilondev and eps_trace_over_3 don't have the same dimensions.. could cause trouble
-    if (NSPEC_CRUST_MANTLE_STR_OR_ATT /= NSPEC_CRUST_MANTLE) &
-      stop 'NSPEC_CRUST_MANTLE_STRAINS_ATT /= NSPEC_CRUST_MANTLE'
-    if (NSPEC_CRUST_MANTLE_STRAIN_ONLY /= NSPEC_CRUST_MANTLE) &
-      stop 'NSPEC_CRUST_MANTLE_STRAIN_ONLY /= NSPEC_CRUST_MANTLE'
-
-    write(prname,'(a,i6.6,a)') trim(LOCAL_PATH)//'/'//'proc',myrank,'_'
-    call count_points_movie_volume(prname,ibool_crust_mantle, xstore_crust_mantle,ystore_crust_mantle, &
-                zstore_crust_mantle,MOVIE_TOP,MOVIE_BOTTOM,MOVIE_WEST,MOVIE_EAST,MOVIE_NORTH,MOVIE_SOUTH, &
-                MOVIE_COARSE,npoints_3dmovie,nspecel_3dmovie,num_ibool_3dmovie,mask_ibool,mask_3dmovie)
-
-
-    allocate(nu_3dmovie(3,3,npoints_3dmovie),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating nu for 3d movie')
-
-    call write_movie_volume_mesh(npoints_3dmovie,prname,ibool_crust_mantle,xstore_crust_mantle, &
-                           ystore_crust_mantle,zstore_crust_mantle, muvstore_crust_mantle_3dmovie, &
-                           mask_3dmovie,mask_ibool,num_ibool_3dmovie,nu_3dmovie,MOVIE_COARSE)
-
-    if(myrank == 0) then
-      write(IMAIN,*)
-      write(IMAIN,*) 'Movie volume:'
-      write(IMAIN,*) '  Writing to movie3D*** files on local disk databases directory'
-      if(MOVIE_VOLUME_TYPE == 1) then
-        write(IMAIN,*) '  movie output: strain'
-      else if(MOVIE_VOLUME_TYPE == 2) then
-        write(IMAIN,*) '  movie output: time integral of strain'
-      else if(MOVIE_VOLUME_TYPE == 3) then
-        write(IMAIN,*) '  movie output: potency or integral of strain'
-      else if(MOVIE_VOLUME_TYPE == 4) then
-        write(IMAIN,*) '  movie output: divergence and curl'
-      else if(MOVIE_VOLUME_TYPE == 5) then
-        write(IMAIN,*) '  movie output: displacement'
-      else if(MOVIE_VOLUME_TYPE == 6) then
-        write(IMAIN,*) '  movie output: velocity'
-      endif
-      write(IMAIN,*) '  depth(T,B):',MOVIE_TOP,MOVIE_BOTTOM
-      write(IMAIN,*) '  lon(W,E)  :',MOVIE_WEST,MOVIE_EAST
-      write(IMAIN,*) '  lat(S,N)  :',MOVIE_SOUTH,MOVIE_NORTH
-      write(IMAIN,*) '  Starting at time step:',MOVIE_START, 'ending at:',MOVIE_STOP,'every: ',NTSTEP_BETWEEN_FRAMES
-    endif
-
-  endif ! MOVIE_VOLUME
-
-  ! sets up time increments and rotation constants
-  call prepare_timerun_constants(myrank,NSTEP, &
-                    DT,t0,scale_t,scale_t_inv,scale_displ,scale_veloc, &
-                    deltat,deltatover2,deltatsqover2, &
-                    b_deltat,b_deltatover2,b_deltatsqover2, &
-                    two_omega_earth,A_array_rotation,B_array_rotation, &
-                    b_two_omega_earth, SIMULATION_TYPE)
-
-  ! precomputes gravity factors
-  call prepare_timerun_gravity(myrank, &
-                    minus_g_cmb,minus_g_icb, &
-                    minus_gravity_table,minus_deriv_gravity_table, &
-                    density_table,d_ln_density_dr_table,minus_rho_g_over_kappa_fluid, &
-                    ONE_CRUST,RICB,RCMB,RTOPDDOUBLEPRIME, &
-                    R600,R670,R220,R771,R400,R80,RMOHO,RMIDDLE_CRUST,ROCEAN)
-
-  ! precomputes attenuation factors
-  if(ATTENUATION_VAL) then
-    call prepare_timerun_attenuation(myrank, &
-                factor_scale_crust_mantle,one_minus_sum_beta_crust_mantle,factor_common_crust_mantle, &
-                factor_scale_inner_core,one_minus_sum_beta_inner_core,factor_common_inner_core, &
-                c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-                c22store_crust_mantle,c23store_crust_mantle, &
-                c33store_crust_mantle,c44store_crust_mantle, &
-                c55store_crust_mantle,c66store_crust_mantle, &
-                muvstore_crust_mantle,muhstore_crust_mantle,ispec_is_tiso_crust_mantle, &
-                muvstore_inner_core, &
-                SIMULATION_TYPE,MOVIE_VOLUME,muvstore_crust_mantle_3dmovie, &
-                c11store_inner_core,c12store_inner_core,c13store_inner_core, &
-                c33store_inner_core,c44store_inner_core, &
-                alphaval,betaval,gammaval,b_alphaval,b_betaval,b_gammaval, &
-                deltat,b_deltat,LOCAL_PATH)
-  endif
-
-  if(myrank == 0) then
-
-  write(IMAIN,*) 'for overlapping of communications with calculations:'
-  write(IMAIN,*)
-
-  percentage_edge = 100.*count(is_on_a_slice_edge_crust_mantle(:))/real(NSPEC_CRUST_MANTLE)
-  write(IMAIN,*) 'percentage of edge elements in crust/mantle ',percentage_edge,'%'
-  write(IMAIN,*) 'percentage of volume elements in crust/mantle ',100. - percentage_edge,'%'
-  write(IMAIN,*)
-
-  percentage_edge = 100.*count(is_on_a_slice_edge_outer_core(:))/real(NSPEC_OUTER_CORE)
-  write(IMAIN,*) 'percentage of edge elements in outer core ',percentage_edge,'%'
-  write(IMAIN,*) 'percentage of volume elements in outer core ',100. - percentage_edge,'%'
-  write(IMAIN,*)
-
-  percentage_edge = 100.*count(is_on_a_slice_edge_inner_core(:))/real(NSPEC_INNER_CORE)
-  write(IMAIN,*) 'percentage of edge elements in inner core ',percentage_edge,'%'
-  write(IMAIN,*) 'percentage of volume elements in inner core ',100. - percentage_edge,'%'
-  write(IMAIN,*)
-
-  endif
-
-  if(.not. USE_NONBLOCKING_COMMS) then
-    is_on_a_slice_edge_crust_mantle(:) = .true.
-    is_on_a_slice_edge_outer_core(:) = .true.
-    is_on_a_slice_edge_inner_core(:) = .true.
-  endif
-
-  ! initialize arrays to zero
-  displ_crust_mantle(:,:) = 0._CUSTOM_REAL
-  veloc_crust_mantle(:,:) = 0._CUSTOM_REAL
-  accel_crust_mantle(:,:) = 0._CUSTOM_REAL
-
-  displ_outer_core(:) = 0._CUSTOM_REAL
-  veloc_outer_core(:) = 0._CUSTOM_REAL
-  accel_outer_core(:) = 0._CUSTOM_REAL
-
-  displ_inner_core(:,:) = 0._CUSTOM_REAL
-  veloc_inner_core(:,:) = 0._CUSTOM_REAL
-  accel_inner_core(:,:) = 0._CUSTOM_REAL
-
-  ! put negligible initial value to avoid very slow underflow trapping
-  if(FIX_UNDERFLOW_PROBLEM) then
-    displ_crust_mantle(:,:) = VERYSMALLVAL
-    displ_outer_core(:) = VERYSMALLVAL
-    displ_inner_core(:,:) = VERYSMALLVAL
-  endif
-
-  if (SIMULATION_TYPE == 3) then
-    rho_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
-    beta_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
-    alpha_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
-    if (NOISE_TOMOGRAPHY == 3) Sigma_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
-
-    ! approximate hessian
-    if( APPROXIMATE_HESS_KL ) then
-      allocate( hess_kl_crust_mantle(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE_ADJOINT),stat=ier)
-      if( ier /= 0 ) call exit_MPI(myrank,'error allocating hessian')
-      hess_kl_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
-    endif
-
-    ! For anisotropic kernels (in crust_mantle only)
-    cijkl_kl_crust_mantle(:,:,:,:,:) = 0._CUSTOM_REAL
-
-    rho_kl_outer_core(:,:,:,:) = 0._CUSTOM_REAL
-    alpha_kl_outer_core(:,:,:,:) = 0._CUSTOM_REAL
-
-    rho_kl_inner_core(:,:,:,:) = 0._CUSTOM_REAL
-    beta_kl_inner_core(:,:,:,:) = 0._CUSTOM_REAL
-    alpha_kl_inner_core(:,:,:,:) = 0._CUSTOM_REAL
-
-    div_displ_outer_core(:,:,:,:) = 0._CUSTOM_REAL
-    b_div_displ_outer_core(:,:,:,:) = 0._CUSTOM_REAL
-
-    ! deviatoric kernel check
-    if( deviatoric_outercore) then
-      nspec_beta_kl_outer_core = NSPEC_OUTER_CORE_ADJOINT
-    else
-      nspec_beta_kl_outer_core = 1
-    endif
-    allocate(beta_kl_outer_core(NGLLX,NGLLY,NGLLZ,nspec_beta_kl_outer_core),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating beta outercore')
-    beta_kl_outer_core(:,:,:,:) = 0._CUSTOM_REAL
-  endif
-
-  ! initialize to be on the save side for adjoint runs SIMULATION_TYPE==2
-  eps_trace_over_3_crust_mantle(:,:,:,:) = 0._CUSTOM_REAL
-  epsilondev_crust_mantle(:,:,:,:,:) = 0._CUSTOM_REAL
-  eps_trace_over_3_inner_core(:,:,:,:) = 0._CUSTOM_REAL
-  epsilondev_inner_core(:,:,:,:,:) = 0._CUSTOM_REAL
-  if(FIX_UNDERFLOW_PROBLEM) then
-    eps_trace_over_3_crust_mantle(:,:,:,:) = VERYSMALLVAL
-    epsilondev_crust_mantle(:,:,:,:,:) = VERYSMALLVAL
-    eps_trace_over_3_inner_core(:,:,:,:) = VERYSMALLVAL
-    epsilondev_inner_core(:,:,:,:,:) = VERYSMALLVAL
-  endif
-
-  if (COMPUTE_AND_STORE_STRAIN) then
-    if(MOVIE_VOLUME .and. (MOVIE_VOLUME_TYPE == 2 .or. MOVIE_VOLUME_TYPE == 3)) then
-      Iepsilondev_crust_mantle(:,:,:,:,:) = 0._CUSTOM_REAL
-      Ieps_trace_over_3_crust_mantle(:,:,:,:)=0._CUSTOM_REAL
-    endif
-  endif
-
-  ! clear memory variables if attenuation
-  if(ATTENUATION_VAL) then
-    R_memory_crust_mantle(:,:,:,:,:,:) = 0._CUSTOM_REAL
-    R_memory_inner_core(:,:,:,:,:,:) = 0._CUSTOM_REAL
-    if(FIX_UNDERFLOW_PROBLEM) then
-      R_memory_crust_mantle(:,:,:,:,:,:) = VERYSMALLVAL
-      R_memory_inner_core(:,:,:,:,:,:) = VERYSMALLVAL
-    endif
-  endif
-
-  ! reads files back from local disk or MT tape system if restart file
-  ! note: for SIMULATION_TYPE 3 simulations, the stored wavefields
-  !          will be read in the time loop after the Newmark time scheme update.
-  !          this makes indexing and timing easier to match with adjoint wavefields indexing.
-  call read_forward_arrays_startrun(myrank,NSTEP, &
-                    SIMULATION_TYPE,NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN, &
-                    it_begin,it_end, &
-                    displ_crust_mantle,veloc_crust_mantle,accel_crust_mantle, &
-                    displ_inner_core,veloc_inner_core,accel_inner_core, &
-                    displ_outer_core,veloc_outer_core,accel_outer_core, &
-                    R_memory_crust_mantle,R_memory_inner_core, &
-                    epsilondev_crust_mantle,epsilondev_inner_core, &
-                    A_array_rotation,B_array_rotation, &
-                    b_displ_crust_mantle,b_veloc_crust_mantle,b_accel_crust_mantle, &
-                    b_displ_inner_core,b_veloc_inner_core,b_accel_inner_core, &
-                    b_displ_outer_core,b_veloc_outer_core,b_accel_outer_core, &
-                    b_R_memory_crust_mantle,b_R_memory_inner_core, &
-                    b_epsilondev_crust_mantle,b_epsilondev_inner_core, &
-                    b_A_array_rotation,b_B_array_rotation,LOCAL_PATH)
-
-!<YANGL
-  ! NOISE TOMOGRAPHY
-  if ( NOISE_TOMOGRAPHY /= 0 ) then
-    allocate(noise_sourcearray(NDIM,NGLLX,NGLLY,NGLLZ,NSTEP), &
-            normal_x_noise(nmovie_points), &
-            normal_y_noise(nmovie_points), &
-            normal_z_noise(nmovie_points), &
-            mask_noise(nmovie_points), &
-            noise_surface_movie(NDIM,NGLLX,NGLLY,NSPEC2D_TOP(IREGION_CRUST_MANTLE)),stat=ier)
-    if( ier /= 0 ) call exit_MPI(myrank,'error allocating noise arrays')
-
-    noise_sourcearray(:,:,:,:,:) = 0._CUSTOM_REAL
-    normal_x_noise(:)            = 0._CUSTOM_REAL
-    normal_y_noise(:)            = 0._CUSTOM_REAL
-    normal_z_noise(:)            = 0._CUSTOM_REAL
-    mask_noise(:)                = 0._CUSTOM_REAL
-    noise_surface_movie(:,:,:,:) = 0._CUSTOM_REAL
-
-    call read_parameters_noise(myrank,nrec,NSTEP,nmovie_points, &
-                              islice_selected_rec,xi_receiver,eta_receiver,gamma_receiver,nu, &
-                              noise_sourcearray,xigll,yigll,zigll,NSPEC2D_TOP(IREGION_CRUST_MANTLE), &
-                              NIT, ibool_crust_mantle, ibelm_top_crust_mantle, &
-                              xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-                              irec_master_noise,normal_x_noise,normal_y_noise,normal_z_noise,mask_noise)
-
-    call check_parameters_noise(myrank,NOISE_TOMOGRAPHY,SIMULATION_TYPE,SAVE_FORWARD, &
-                              NUMBER_OF_RUNS, NUMBER_OF_THIS_RUN,ROTATE_SEISMOGRAMS_RT, &
-                              SAVE_ALL_SEISMOS_IN_ONE_FILE, USE_BINARY_FOR_LARGE_FILE, &
-                              MOVIE_COARSE,LOCAL_PATH,NSPEC2D_TOP(IREGION_CRUST_MANTLE),NSTEP)
-  endif
-!>YANGL
-
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-
-!
-!   s t a r t   t i m e   i t e r a t i o n s
-!
-
-! synchronize all processes to make sure everybody is ready to start time loop
-  call MPI_BARRIER(MPI_COMM_WORLD,ier)
-  if(myrank == 0) write(IMAIN,*) 'All processes are synchronized before time loop'
-
-  if(myrank == 0) then
-    write(IMAIN,*)
-    write(IMAIN,*) 'Starting time iteration loop...'
-    write(IMAIN,*)
-  endif
-
-! create an empty file to monitor the start of the simulation
-  if(myrank == 0) then
-    open(unit=IOUT,file=trim(OUTPUT_FILES)//'/starttimeloop.txt',status='unknown',action='write')
-    write(IOUT,*) 'hello, starting time loop'
-    close(IOUT)
-  endif
-
-! initialize variables for writing seismograms
-  seismo_offset = it_begin-1
-  seismo_current = 0
-
-  imodulo_NGLOB_CRUST_MANTLE = mod(NGLOB_CRUST_MANTLE,3)
-  imodulo_NGLOB_OUTER_CORE = mod(NGLOB_OUTER_CORE,4)
-  imodulo_NGLOB_INNER_CORE = mod(NGLOB_INNER_CORE,3)
-
-! get MPI starting time
-  time_start = MPI_WTIME()
-
-! *********************************************************
-! ************* MAIN LOOP OVER THE TIME STEPS *************
-! *********************************************************
-
-  do it = it_begin,it_end
-
-    ! update position in seismograms
-    seismo_current = seismo_current + 1
-
-! way 1:
-!    ! mantle
-!    do i=1,NGLOB_CRUST_MANTLE
-!      displ_crust_mantle(:,i) = displ_crust_mantle(:,i) &
-!        + deltat*veloc_crust_mantle(:,i) + deltatsqover2*accel_crust_mantle(:,i)
-!      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) &
-!        + deltatover2*accel_crust_mantle(:,i)
-!    enddo
-!    ! outer core
-!    do i=1,NGLOB_OUTER_CORE
-!      displ_outer_core(i) = displ_outer_core(i) &
-!        + deltat*veloc_outer_core(i) + deltatsqover2*accel_outer_core(i)
-!      veloc_outer_core(i) = veloc_outer_core(i) &
-!        + deltatover2*accel_outer_core(i)
-!    enddo
-!    ! inner core
-!    do i=1,NGLOB_INNER_CORE
-!      displ_inner_core(:,i) = displ_inner_core(:,i) &
-!        + deltat*veloc_inner_core(:,i) + deltatsqover2*accel_inner_core(:,i)
-!      veloc_inner_core(:,i) = veloc_inner_core(:,i) &
-!        + deltatover2*accel_inner_core(:,i)
-!    enddo
-
-! way 2:
-! One common technique in computational science to help enhance pipelining is loop unrolling
-!
-! we're accessing NDIM=3 components at each line,
-! that is, for an iteration, the register must contain
-! NDIM * displ_ + NDIM * veloc_ + NDIM * accel + deltat + deltatsq..
-! in most cases a real (CUSTOM_REAL) value will have 4 bytes,
-! assuming a default cache size of about 128 bytes, we unroll here in steps of 3, thus 29 reals or 118 bytes,
-! rather than with steps of 4
-  if(imodulo_NGLOB_CRUST_MANTLE >= 1) then
-    do i = 1,imodulo_NGLOB_CRUST_MANTLE
-      displ_crust_mantle(:,i) = displ_crust_mantle(:,i) &
-        + deltat*veloc_crust_mantle(:,i) + deltatsqover2*accel_crust_mantle(:,i)
-
-      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) &
-        + deltatover2*accel_crust_mantle(:,i)
-
-      accel_crust_mantle(:,i) = 0._CUSTOM_REAL
-    enddo
-  endif
-
-    do i = imodulo_NGLOB_CRUST_MANTLE+1,NGLOB_CRUST_MANTLE, 3 ! in steps of 3
-      displ_crust_mantle(:,i) = displ_crust_mantle(:,i) &
-        + deltat*veloc_crust_mantle(:,i) + deltatsqover2*accel_crust_mantle(:,i)
-      displ_crust_mantle(:,i+1) = displ_crust_mantle(:,i+1) &
-        + deltat*veloc_crust_mantle(:,i+1) + deltatsqover2*accel_crust_mantle(:,i+1)
-      displ_crust_mantle(:,i+2) = displ_crust_mantle(:,i+2) &
-        + deltat*veloc_crust_mantle(:,i+2) + deltatsqover2*accel_crust_mantle(:,i+2)
-
-
-      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) &
-        + deltatover2*accel_crust_mantle(:,i)
-      veloc_crust_mantle(:,i+1) = veloc_crust_mantle(:,i+1) &
-        + deltatover2*accel_crust_mantle(:,i+1)
-      veloc_crust_mantle(:,i+2) = veloc_crust_mantle(:,i+2) &
-        + deltatover2*accel_crust_mantle(:,i+2)
-
-      ! set acceleration to zero
-      ! note: we do initialize acceleration in this loop since it is read already into the cache,
-      !           otherwise it would have to be read in again for this explicitly,
-      !           which would make this step more expensive
-      accel_crust_mantle(:,i) = 0._CUSTOM_REAL
-      accel_crust_mantle(:,i+1) = 0._CUSTOM_REAL
-      accel_crust_mantle(:,i+2) = 0._CUSTOM_REAL
-    enddo
-
-
-    ! outer core
-  if(imodulo_NGLOB_OUTER_CORE >= 1) then
-    do i = 1,imodulo_NGLOB_OUTER_CORE
-      displ_outer_core(i) = displ_outer_core(i) &
-        + deltat*veloc_outer_core(i) + deltatsqover2*accel_outer_core(i)
-
-      veloc_outer_core(i) = veloc_outer_core(i) &
-        + deltatover2*accel_outer_core(i)
-
-      accel_outer_core(i) = 0._CUSTOM_REAL
-    enddo
-  endif
-    do i = imodulo_NGLOB_OUTER_CORE+1,NGLOB_OUTER_CORE, 4 ! in steps of 4
-      displ_outer_core(i) = displ_outer_core(i) &
-        + deltat*veloc_outer_core(i) + deltatsqover2*accel_outer_core(i)
-      displ_outer_core(i+1) = displ_outer_core(i+1) &
-        + deltat*veloc_outer_core(i+1) + deltatsqover2*accel_outer_core(i+1)
-      displ_outer_core(i+2) = displ_outer_core(i+2) &
-        + deltat*veloc_outer_core(i+2) + deltatsqover2*accel_outer_core(i+2)
-      displ_outer_core(i+3) = displ_outer_core(i+3) &
-        + deltat*veloc_outer_core(i+3) + deltatsqover2*accel_outer_core(i+3)
-
-      veloc_outer_core(i) = veloc_outer_core(i) &
-        + deltatover2*accel_outer_core(i)
-      veloc_outer_core(i+1) = veloc_outer_core(i+1) &
-        + deltatover2*accel_outer_core(i+1)
-      veloc_outer_core(i+2) = veloc_outer_core(i+2) &
-        + deltatover2*accel_outer_core(i+2)
-      veloc_outer_core(i+3) = veloc_outer_core(i+3) &
-        + deltatover2*accel_outer_core(i+3)
-
-      accel_outer_core(i) = 0._CUSTOM_REAL
-      accel_outer_core(i+1) = 0._CUSTOM_REAL
-      accel_outer_core(i+2) = 0._CUSTOM_REAL
-      accel_outer_core(i+3) = 0._CUSTOM_REAL
-    enddo
-
-
-    ! inner core
-  if(imodulo_NGLOB_INNER_CORE >= 1) then
-    do i = 1,imodulo_NGLOB_INNER_CORE
-      displ_inner_core(:,i) = displ_inner_core(:,i) &
-        + deltat*veloc_inner_core(:,i) + deltatsqover2*accel_inner_core(:,i)
-
-      veloc_inner_core(:,i) = veloc_inner_core(:,i) &
-        + deltatover2*accel_inner_core(:,i)
-
-      accel_inner_core(:,i) = 0._CUSTOM_REAL
-    enddo
-  endif
-    do i = imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE, 3 ! in steps of 3
-      displ_inner_core(:,i) = displ_inner_core(:,i) &
-        + deltat*veloc_inner_core(:,i) + deltatsqover2*accel_inner_core(:,i)
-      displ_inner_core(:,i+1) = displ_inner_core(:,i+1) &
-        + deltat*veloc_inner_core(:,i+1) + deltatsqover2*accel_inner_core(:,i+1)
-      displ_inner_core(:,i+2) = displ_inner_core(:,i+2) &
-        + deltat*veloc_inner_core(:,i+2) + deltatsqover2*accel_inner_core(:,i+2)
-
-
-      veloc_inner_core(:,i) = veloc_inner_core(:,i) &
-        + deltatover2*accel_inner_core(:,i)
-      veloc_inner_core(:,i+1) = veloc_inner_core(:,i+1) &
-        + deltatover2*accel_inner_core(:,i+1)
-      veloc_inner_core(:,i+2) = veloc_inner_core(:,i+2) &
-        + deltatover2*accel_inner_core(:,i+2)
-
-      accel_inner_core(:,i) = 0._CUSTOM_REAL
-      accel_inner_core(:,i+1) = 0._CUSTOM_REAL
-      accel_inner_core(:,i+2) = 0._CUSTOM_REAL
-    enddo
-
-
-
-    ! backward field
-    if (SIMULATION_TYPE == 3) then
-! way 1:
-!      do i=1,NGLOB_CRUST_MANTLE
-!        b_displ_crust_mantle(:,i) = b_displ_crust_mantle(:,i) &
-!          + b_deltat*b_veloc_crust_mantle(:,i) + b_deltatsqover2*b_accel_crust_mantle(:,i)
-!        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) &
-!          + b_deltatover2*b_accel_crust_mantle(:,i)
-!      enddo
-!      do i=1,NGLOB_OUTER_CORE
-!        b_displ_outer_core(i) = b_displ_outer_core(i) &
-!          + b_deltat*b_veloc_outer_core(i) + b_deltatsqover2*b_accel_outer_core(i)
-!        b_veloc_outer_core(i) = b_veloc_outer_core(i) &
-!          + b_deltatover2*b_accel_outer_core(i)
-!      enddo
-!      do i=1,NGLOB_INNER_CORE
-!        b_displ_inner_core(:,i) = b_displ_inner_core(:,i) &
-!          + b_deltat*b_veloc_inner_core(:,i) + b_deltatsqover2*b_accel_inner_core(:,i)
-!        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) &
-!          + b_deltatover2*b_accel_inner_core(:,i)
-!      enddo
-
-! way 2:
-    if(imodulo_NGLOB_CRUST_MANTLE >= 1) then
-      do i=1,imodulo_NGLOB_CRUST_MANTLE
-        b_displ_crust_mantle(:,i) = b_displ_crust_mantle(:,i) &
-          + b_deltat*b_veloc_crust_mantle(:,i) + b_deltatsqover2*b_accel_crust_mantle(:,i)
-        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) &
-          + b_deltatover2*b_accel_crust_mantle(:,i)
-        b_accel_crust_mantle(:,i) = 0._CUSTOM_REAL
-      enddo
-    endif
-
-      do i=imodulo_NGLOB_CRUST_MANTLE+1,NGLOB_CRUST_MANTLE,3
-        b_displ_crust_mantle(:,i) = b_displ_crust_mantle(:,i) &
-          + b_deltat*b_veloc_crust_mantle(:,i) + b_deltatsqover2*b_accel_crust_mantle(:,i)
-        b_displ_crust_mantle(:,i+1) = b_displ_crust_mantle(:,i+1) &
-          + b_deltat*b_veloc_crust_mantle(:,i+1) + b_deltatsqover2*b_accel_crust_mantle(:,i+1)
-        b_displ_crust_mantle(:,i+2) = b_displ_crust_mantle(:,i+2) &
-          + b_deltat*b_veloc_crust_mantle(:,i+2) + b_deltatsqover2*b_accel_crust_mantle(:,i+2)
-
-
-        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) &
-          + b_deltatover2*b_accel_crust_mantle(:,i)
-        b_veloc_crust_mantle(:,i+1) = b_veloc_crust_mantle(:,i+1) &
-          + b_deltatover2*b_accel_crust_mantle(:,i+1)
-        b_veloc_crust_mantle(:,i+2) = b_veloc_crust_mantle(:,i+2) &
-          + b_deltatover2*b_accel_crust_mantle(:,i+2)
-
-        b_accel_crust_mantle(:,i) = 0._CUSTOM_REAL
-        b_accel_crust_mantle(:,i+1) = 0._CUSTOM_REAL
-        b_accel_crust_mantle(:,i+2) = 0._CUSTOM_REAL
-      enddo
-
-
-    if(imodulo_NGLOB_OUTER_CORE >= 1) then
-      do i=1,imodulo_NGLOB_OUTER_CORE
-        b_displ_outer_core(i) = b_displ_outer_core(i) &
-          + b_deltat*b_veloc_outer_core(i) + b_deltatsqover2*b_accel_outer_core(i)
-        b_veloc_outer_core(i) = b_veloc_outer_core(i) &
-          + b_deltatover2*b_accel_outer_core(i)
-        b_accel_outer_core(i) = 0._CUSTOM_REAL
-      enddo
-    endif
-      do i=imodulo_NGLOB_OUTER_CORE+1,NGLOB_OUTER_CORE,4
-        b_displ_outer_core(i) = b_displ_outer_core(i) &
-          + b_deltat*b_veloc_outer_core(i) + b_deltatsqover2*b_accel_outer_core(i)
-        b_displ_outer_core(i+1) = b_displ_outer_core(i+1) &
-          + b_deltat*b_veloc_outer_core(i+1) + b_deltatsqover2*b_accel_outer_core(i+1)
-        b_displ_outer_core(i+2) = b_displ_outer_core(i+2) &
-          + b_deltat*b_veloc_outer_core(i+2) + b_deltatsqover2*b_accel_outer_core(i+2)
-        b_displ_outer_core(i+3) = b_displ_outer_core(i+3) &
-          + b_deltat*b_veloc_outer_core(i+3) + b_deltatsqover2*b_accel_outer_core(i+3)
-
-        b_veloc_outer_core(i) = b_veloc_outer_core(i) &
-          + b_deltatover2*b_accel_outer_core(i)
-        b_veloc_outer_core(i+1) = b_veloc_outer_core(i+1) &
-          + b_deltatover2*b_accel_outer_core(i+1)
-        b_veloc_outer_core(i+2) = b_veloc_outer_core(i+2) &
-          + b_deltatover2*b_accel_outer_core(i+2)
-        b_veloc_outer_core(i+3) = b_veloc_outer_core(i+3) &
-          + b_deltatover2*b_accel_outer_core(i+3)
-
-        b_accel_outer_core(i) = 0._CUSTOM_REAL
-        b_accel_outer_core(i+1) = 0._CUSTOM_REAL
-        b_accel_outer_core(i+2) = 0._CUSTOM_REAL
-        b_accel_outer_core(i+3) = 0._CUSTOM_REAL
-      enddo
-
-
-    if(imodulo_NGLOB_INNER_CORE >= 1) then
-      do i=1,imodulo_NGLOB_INNER_CORE
-        b_displ_inner_core(:,i) = b_displ_inner_core(:,i) &
-          + b_deltat*b_veloc_inner_core(:,i) + b_deltatsqover2*b_accel_inner_core(:,i)
-        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) &
-          + b_deltatover2*b_accel_inner_core(:,i)
-        b_accel_inner_core(:,i) = 0._CUSTOM_REAL
-      enddo
-    endif
-      do i=imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE,3
-        b_displ_inner_core(:,i) = b_displ_inner_core(:,i) &
-          + b_deltat*b_veloc_inner_core(:,i) + b_deltatsqover2*b_accel_inner_core(:,i)
-        b_displ_inner_core(:,i+1) = b_displ_inner_core(:,i+1) &
-          + b_deltat*b_veloc_inner_core(:,i+1) + b_deltatsqover2*b_accel_inner_core(:,i+1)
-        b_displ_inner_core(:,i+2) = b_displ_inner_core(:,i+2) &
-          + b_deltat*b_veloc_inner_core(:,i+2) + b_deltatsqover2*b_accel_inner_core(:,i+2)
-
-        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) &
-          + b_deltatover2*b_accel_inner_core(:,i)
-        b_veloc_inner_core(:,i+1) = b_veloc_inner_core(:,i+1) &
-          + b_deltatover2*b_accel_inner_core(:,i+1)
-        b_veloc_inner_core(:,i+2) = b_veloc_inner_core(:,i+2) &
-          + b_deltatover2*b_accel_inner_core(:,i+2)
-
-        b_accel_inner_core(:,i) = 0._CUSTOM_REAL
-        b_accel_inner_core(:,i+1) = 0._CUSTOM_REAL
-        b_accel_inner_core(:,i+2) = 0._CUSTOM_REAL
-      enddo
-
-    endif
-
-    ! integral of strain for adjoint movie volume
-    if(MOVIE_VOLUME .and. (MOVIE_VOLUME_TYPE == 2 .or. MOVIE_VOLUME_TYPE == 3) ) then
-      Iepsilondev_crust_mantle(:,:,:,:,:) = Iepsilondev_crust_mantle(:,:,:,:,:)  &
-                                              + deltat*epsilondev_crust_mantle(:,:,:,:,:)
-      Ieps_trace_over_3_crust_mantle(:,:,:,:) = Ieps_trace_over_3_crust_mantle(:,:,:,:) &
-                                              + deltat*eps_trace_over_3_crust_mantle(:,:,:,:)
-    endif
-
-    ! daniel: debugging
-    !if( maxval(displ_crust_mantle(1,:)**2 + &
-    !                displ_crust_mantle(2,:)**2 + displ_crust_mantle(3,:)**2) > 1.e4 ) then
-    !  print*,'slice',myrank
-    !  print*,'  crust_mantle displ:', maxval(displ_crust_mantle(1,:)), &
-    !           maxval(displ_crust_mantle(2,:)),maxval(displ_crust_mantle(3,:))
-    !  print*,'  indxs: ',maxloc( displ_crust_mantle(1,:)),maxloc( displ_crust_mantle(2,:)),maxloc( displ_crust_mantle(3,:))
-    !  indx = maxloc( displ_crust_mantle(3,:) )
-    !  rval = xstore_crust_mantle(indx(1))
-    !  thetaval = ystore_crust_mantle(indx(1))
-    !  phival = zstore_crust_mantle(indx(1))
-    !  !thetaval = PI/2.0d0-datan(1.006760466d0*dcos(dble(thetaval))/dmax1(TINYVAL,dsin(dble(thetaval))))
-    !  print*,'r/lat/lon:',rval*R_EARTH_KM,90.0-thetaval*180./PI,phival*180./PI
-    !  call rthetaphi_2_xyz(rval,thetaval,phival,xstore_crust_mantle(indx(1)),&
-    !                     ystore_crust_mantle(indx(1)),zstore_crust_mantle(indx(1)))
-    !  print*,'x/y/z:',rval,thetaval,phival
-    !  call exit_MPI(myrank,'error stability')
-    !endif
-
-
-    ! compute the maximum of the norm of the displacement
-    ! in all the slices using an MPI reduction
-    ! and output timestamp file to check that simulation is running fine
-    if(mod(it,NTSTEP_BETWEEN_OUTPUT_INFO) == 0 .or. it == 5 .or. it == NSTEP) &
-      call check_simulation_stability(it,displ_crust_mantle,displ_inner_core,displ_outer_core, &
-                          b_displ_crust_mantle,b_displ_inner_core,b_displ_outer_core, &
-                          eps_trace_over_3_crust_mantle,epsilondev_crust_mantle, &
-                          SIMULATION_TYPE,OUTPUT_FILES,time_start,DT,t0,NSTEP, &
-                          myrank)
-
-
-    ! ****************************************************
-    !   big loop over all spectral elements in the fluid
-    ! ****************************************************
-
-    ! compute internal forces in the fluid region
-    if(CUSTOM_REAL == SIZE_REAL) then
-      time = sngl((dble(it-1)*DT-t0)*scale_t_inv)
-    else
-      time = (dble(it-1)*DT-t0)*scale_t_inv
-    endif
-
-    iphase = 0 ! do not start any non blocking communications at this stage
-    icall = 1  ! compute all the outer elements first in the case of non blocking MPI
-
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-      ! uses Deville et al. (2002) routine
-      call compute_forces_outer_core_Dev(time,deltat,two_omega_earth, &
-           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid, &
-           displ_outer_core,accel_outer_core,div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
-           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-    else
-      ! div_displ_outer_core is initialized to zero in the following subroutine.
-      call compute_forces_outer_core(time,deltat,two_omega_earth, &
-           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid, &
-           displ_outer_core,accel_outer_core,div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
-           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-    endif
-
-    if (SIMULATION_TYPE == 3) then
-      ! note on backward/reconstructed wavefields:
-      !       time for b_displ( it=1 ) corresponds to (NSTEP - 1)*DT - t0  (after Newmark scheme...)
-      !       as we start with saved wavefields b_displ( 1 ) <-> displ( NSTEP ) which correspond
-      !       to a time (NSTEP - (it-1) - 1)*DT - t0
-      !       for reconstructing the rotational contributions
-      if(CUSTOM_REAL == SIZE_REAL) then
-        time = sngl((dble(NSTEP-it)*DT-t0)*scale_t_inv)
-      else
-        time = (dble(NSTEP-it)*DT-t0)*scale_t_inv
-      endif
-
-      b_iphase = 0 ! do not start any non blocking communications at this stage
-      b_icall = 1  ! compute all the outer elements first in the case of non blocking MPI
-
-      if( USE_DEVILLE_PRODUCTS_VAL ) then
-        ! uses Deville et al. (2002) routine
-        call compute_forces_outer_core_Dev(time,b_deltat,b_two_omega_earth, &
-           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid, &
-           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
-           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-      else
-        call compute_forces_outer_core(time,b_deltat,b_two_omega_earth, &
-           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid, &
-           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
-           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-      endif
-    endif
-
-    ! Stacey absorbing boundaries
-    if(NCHUNKS_VAL /= 6 .and. ABSORBING_CONDITIONS) then
-      call compute_stacey_outer_core(ichunk,SIMULATION_TYPE,SAVE_FORWARD, &
-                              NSTEP,it,ibool_outer_core, &
-                              veloc_outer_core,accel_outer_core,b_accel_outer_core, &
-                              vp_outer_core,wgllwgll_xz,wgllwgll_yz,wgllwgll_xy, &
-                              jacobian2D_bottom_outer_core, &
-                              jacobian2D_xmin_outer_core,jacobian2D_xmax_outer_core, &
-                              jacobian2D_ymin_outer_core,jacobian2D_ymax_outer_core, &
-                              ibelm_bottom_outer_core, &
-                              ibelm_xmin_outer_core,ibelm_xmax_outer_core, &
-                              ibelm_ymin_outer_core,ibelm_ymax_outer_core, &
-                              nimin_outer_core,nimax_outer_core, &
-                              njmin_outer_core,njmax_outer_core, &
-                              nkmin_xi_outer_core,nkmin_eta_outer_core, &
-                              NSPEC2D_BOTTOM, &
-                              nspec2D_xmin_outer_core,nspec2D_xmax_outer_core, &
-                              nspec2D_ymin_outer_core,nspec2D_ymax_outer_core, &
-                              reclen_zmin, &
-                              reclen_xmin_outer_core,reclen_xmax_outer_core, &
-                              reclen_ymin_outer_core,reclen_ymax_outer_core, &
-                              nabs_zmin_oc, &
-                              nabs_xmin_oc,nabs_xmax_oc,nabs_ymin_oc,nabs_ymax_oc, &
-                              absorb_zmin_outer_core, &
-                              absorb_xmin_outer_core,absorb_xmax_outer_core, &
-                              absorb_ymin_outer_core,absorb_ymax_outer_core)
-    endif ! Stacey conditions
-
-
-    ! ****************************************************
-    ! **********  add matching with solid part  **********
-    ! ****************************************************
-
-    ! only for elements in first matching layer in the fluid
-
-    !---
-    !--- couple with mantle at the top of the outer core
-    !---
-    if(ACTUALLY_COUPLE_FLUID_CMB) &
-      call compute_coupling_fluid_CMB(displ_crust_mantle,b_displ_crust_mantle, &
-                            ibool_crust_mantle,ibelm_bottom_crust_mantle,  &
-                            accel_outer_core,b_accel_outer_core, &
-                            normal_top_outer_core,jacobian2D_top_outer_core, &
-                            wgllwgll_xy,ibool_outer_core,ibelm_top_outer_core, &
-                            SIMULATION_TYPE,NSPEC2D_TOP(IREGION_OUTER_CORE))
-
-    !---
-    !--- couple with inner core at the bottom of the outer core
-    !---
-    if(ACTUALLY_COUPLE_FLUID_ICB) &
-      call compute_coupling_fluid_ICB(displ_inner_core,b_displ_inner_core, &
-                            ibool_inner_core,ibelm_top_inner_core,  &
-                            accel_outer_core,b_accel_outer_core, &
-                            normal_bottom_outer_core,jacobian2D_bottom_outer_core, &
-                            wgllwgll_xy,ibool_outer_core,ibelm_bottom_outer_core, &
-                            SIMULATION_TYPE,NSPEC2D_BOTTOM(IREGION_OUTER_CORE))
-
-
-    ! assemble all the contributions between slices using MPI
-
-    ! outer core
-  if(USE_NONBLOCKING_COMMS) then
-    iphase = 1 ! start the non blocking communications
-    call assemble_MPI_scalar(myrank,accel_outer_core,NGLOB_OUTER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-            iboolfaces_outer_core,iboolcorner_outer_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL,iphase)
-
-    icall = 2 ! now compute all the inner elements in the case of non blocking MPI
-
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-        ! uses Deville et al. (2002) routine
-      call compute_forces_outer_core_Dev(time,deltat,two_omega_earth, &
-           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid,displ_outer_core,accel_outer_core,div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
-           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-    else
-      ! div_displ_outer_core is initialized to zero in the following subroutine.
-      call compute_forces_outer_core(time,deltat,two_omega_earth, &
-           A_array_rotation,B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid,displ_outer_core,accel_outer_core,div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-          buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar,iphase,icall, &
-           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-    endif
-
-    do while (iphase <= 7) ! make sure the last communications are finished and processed
-      call assemble_MPI_scalar(myrank,accel_outer_core,NGLOB_OUTER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-            iboolfaces_outer_core,iboolcorner_outer_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL,iphase)
-    enddo
-
-  else ! if(.not. USE_NONBLOCKING_COMMS) then
-
-    call assemble_MPI_scalar_block(myrank,accel_outer_core,NGLOB_OUTER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_outer_core,iboolright_xi_outer_core, &
-            iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-            iboolfaces_outer_core,iboolcorner_outer_core, &
-            iprocfrom_faces,iprocto_faces,imsg_type, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_scalar,buffer_recv_chunkcorn_scalar, &
-            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL)
-
-  endif
-
-    ! multiply by the inverse of the mass matrix and update velocity
-
-! way 1:
-!    do i=1,NGLOB_OUTER_CORE
-!      accel_outer_core(i) = accel_outer_core(i)*rmass_outer_core(i)
-!      veloc_outer_core(i) = veloc_outer_core(i) + deltatover2*accel_outer_core(i)
-!    enddo
-
-! way 2:
-    if(imodulo_NGLOB_OUTER_CORE >= 1) then
-      do i=1,imodulo_NGLOB_OUTER_CORE
-        accel_outer_core(i) = accel_outer_core(i)*rmass_outer_core(i)
-        veloc_outer_core(i) = veloc_outer_core(i) + deltatover2*accel_outer_core(i)
-      enddo
-    endif
-    do i=imodulo_NGLOB_OUTER_CORE+1,NGLOB_OUTER_CORE,4
-      accel_outer_core(i) = accel_outer_core(i)*rmass_outer_core(i)
-      accel_outer_core(i+1) = accel_outer_core(i+1)*rmass_outer_core(i+1)
-      accel_outer_core(i+2) = accel_outer_core(i+2)*rmass_outer_core(i+2)
-      accel_outer_core(i+3) = accel_outer_core(i+3)*rmass_outer_core(i+3)
-
-      veloc_outer_core(i) = veloc_outer_core(i) + deltatover2*accel_outer_core(i)
-      veloc_outer_core(i+1) = veloc_outer_core(i+1) + deltatover2*accel_outer_core(i+1)
-      veloc_outer_core(i+2) = veloc_outer_core(i+2) + deltatover2*accel_outer_core(i+2)
-      veloc_outer_core(i+3) = veloc_outer_core(i+3) + deltatover2*accel_outer_core(i+3)
-    enddo
-
-    if (SIMULATION_TYPE == 3) then
-
-! ------------------- new non blocking implementation -------------------
-
-    ! outer core
-  if(USE_NONBLOCKING_COMMS) then
-    b_iphase = 1 ! start the non blocking communications
-    call assemble_MPI_scalar(myrank,b_accel_outer_core,NGLOB_OUTER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-            iboolfaces_outer_core,iboolcorner_outer_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL,b_iphase)
-
-    b_icall = 2 ! now compute all the inner elements in the case of non blocking MPI
-
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-        ! uses Deville et al. (2002) routine
-      call compute_forces_outer_core_Dev(time,b_deltat,b_two_omega_earth, &
-           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid, &
-           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
-           hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-    else
-      ! div_displ_outer_core is initialized to zero in the following subroutine.
-      call compute_forces_outer_core(time,b_deltat,b_two_omega_earth, &
-           b_A_array_rotation,b_B_array_rotation,d_ln_density_dr_table, &
-           minus_rho_g_over_kappa_fluid, &
-           b_displ_outer_core,b_accel_outer_core,b_div_displ_outer_core, &
-           xstore_outer_core,ystore_outer_core,zstore_outer_core, &
-           xix_outer_core,xiy_outer_core,xiz_outer_core, &
-           etax_outer_core,etay_outer_core,etaz_outer_core, &
-           gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-          is_on_a_slice_edge_outer_core, &
-          myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-          iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-          npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-          iboolfaces_outer_core,iboolcorner_outer_core, &
-          iprocfrom_faces,iprocto_faces, &
-          iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-          b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-          b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar,b_iphase,b_icall, &
-           hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-           wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-           ibool_outer_core,MOVIE_VOLUME)
-    endif
-
-    do while (b_iphase <= 7) ! make sure the last communications are finished and processed
-      call assemble_MPI_scalar(myrank,b_accel_outer_core,NGLOB_OUTER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_outer_core,iboolright_xi_outer_core,iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-            iboolfaces_outer_core,iboolcorner_outer_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL,b_iphase)
-    enddo
-
-  else ! if(.not. USE_NONBLOCKING_COMMS) then
-
-    call assemble_MPI_scalar_block(myrank,b_accel_outer_core,NGLOB_OUTER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_outer_core,iboolright_xi_outer_core, &
-            iboolleft_eta_outer_core,iboolright_eta_outer_core, &
-            npoin2D_faces_outer_core,npoin2D_xi_outer_core,npoin2D_eta_outer_core, &
-            iboolfaces_outer_core,iboolcorner_outer_core, &
-            iprocfrom_faces,iprocto_faces,imsg_type, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_scalar,b_buffer_recv_chunkcorn_scalar, &
-            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_OUTER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_OUTER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL)
-
-  endif
-
-! ------------------- new non blocking implementation -------------------
-
-! way 1:
-!      do i=1,NGLOB_OUTER_CORE
-!        b_accel_outer_core(i) = b_accel_outer_core(i)*rmass_outer_core(i)
-!        b_veloc_outer_core(i) = b_veloc_outer_core(i) + b_deltatover2*b_accel_outer_core(i)
-!      enddo
-
-! way 2:
-    if(imodulo_NGLOB_OUTER_CORE >= 1) then
-      do i=1,imodulo_NGLOB_OUTER_CORE
-        b_accel_outer_core(i) = b_accel_outer_core(i)*rmass_outer_core(i)
-        b_veloc_outer_core(i) = b_veloc_outer_core(i) + b_deltatover2*b_accel_outer_core(i)
-      enddo
-    endif
-      do i=imodulo_NGLOB_OUTER_CORE+1,NGLOB_OUTER_CORE,4
-        b_accel_outer_core(i) = b_accel_outer_core(i)*rmass_outer_core(i)
-        b_accel_outer_core(i+1) = b_accel_outer_core(i+1)*rmass_outer_core(i+1)
-        b_accel_outer_core(i+2) = b_accel_outer_core(i+2)*rmass_outer_core(i+2)
-        b_accel_outer_core(i+3) = b_accel_outer_core(i+3)*rmass_outer_core(i+3)
-
-        b_veloc_outer_core(i) = b_veloc_outer_core(i) + b_deltatover2*b_accel_outer_core(i)
-        b_veloc_outer_core(i+1) = b_veloc_outer_core(i+1) + b_deltatover2*b_accel_outer_core(i+1)
-        b_veloc_outer_core(i+2) = b_veloc_outer_core(i+2) + b_deltatover2*b_accel_outer_core(i+2)
-        b_veloc_outer_core(i+3) = b_veloc_outer_core(i+3) + b_deltatover2*b_accel_outer_core(i+3)
-      enddo
-
-    endif
-
-    ! ****************************************************
-    !   big loop over all spectral elements in the solid
-    ! ****************************************************
-
-    ! compute internal forces in the solid regions
-
-    ! for anisotropy and gravity, x y and z contain r theta and phi
-
-    iphase = 0 ! do not start any non blocking communications at this stage
-    iphase_CC = 0 ! do not start any non blocking communications at this stage
-    icall = 1  ! compute all the outer elements first in the case of non blocking MPI
-
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-      call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_crust_mantle,accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,icall, &
-            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT, &
-          hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-      ! --idoubling_crust_mantle, &
-          R_memory_crust_mantle,epsilondev_crust_mantle, &
-          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          alphaval,betaval,gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-    else
-      call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_crust_mantle,accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,icall, &
-            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz, &
-          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-        ! --idoubling_crust_mantle, &
-          R_memory_crust_mantle,epsilondev_crust_mantle, &
-          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          alphaval,betaval,gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-    endif
-
-    if (SIMULATION_TYPE == 3 ) then
-
-      b_iphase = 0 ! do not start any non blocking communications at this stage
-      b_iphase_CC = 0 ! do not start any non blocking communications at this stage
-      b_icall = 1  ! compute all the outer elements first in the case of non blocking MPI
-
-    ! for anisotropy and gravity, x y and z contain r theta and phi
-      if( USE_DEVILLE_PRODUCTS_VAL ) then
-        call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_crust_mantle,b_accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,b_icall, &
-            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT, &
-          hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-     ! --     idoubling_crust_mantle, &
-          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
-          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-      else
-        call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_crust_mantle,b_accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,b_icall, &
-            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz, &
-          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-      ! --idoubling_crust_mantle, &
-          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
-          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-
-      endif
-    endif
-
-    ! Deville routine
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-      call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_inner_core,accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,icall, &
-            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          alphaval,betaval,gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-    else
-      call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_inner_core,accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,icall, &
-            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          alphaval,betaval,gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-    endif
-
-    if (SIMULATION_TYPE == 3) then
-      if( USE_DEVILLE_PRODUCTS_VAL ) then
-        call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_inner_core,b_accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,b_icall, &
-            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          b_alphaval,b_betaval,b_gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-      else
-        call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_inner_core,b_accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,b_icall, &
-            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          b_alphaval,b_betaval,b_gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-      endif
-    endif
-
-    ! Stacey
-    if(NCHUNKS_VAL /= 6 .and. ABSORBING_CONDITIONS) then
-      call compute_stacey_crust_mantle(ichunk,SIMULATION_TYPE, &
-                              NSTEP,it,SAVE_FORWARD,ibool_crust_mantle, &
-                              veloc_crust_mantle,accel_crust_mantle,b_accel_crust_mantle, &
-                              jacobian2D_xmin_crust_mantle,jacobian2D_xmax_crust_mantle, &
-                              jacobian2D_ymin_crust_mantle,jacobian2D_ymax_crust_mantle, &
-                              wgllwgll_xz,wgllwgll_yz, &
-                              normal_xmin_crust_mantle,normal_xmax_crust_mantle, &
-                              normal_ymin_crust_mantle,normal_ymax_crust_mantle, &
-                              rho_vp_crust_mantle,rho_vs_crust_mantle, &
-                              ibelm_xmin_crust_mantle,ibelm_xmax_crust_mantle, &
-                              ibelm_ymin_crust_mantle,ibelm_ymax_crust_mantle, &
-                              nimin_crust_mantle,nimax_crust_mantle, &
-                              njmin_crust_mantle,njmax_crust_mantle, &
-                              nkmin_xi_crust_mantle,nkmin_eta_crust_mantle, &
-                              nspec2D_xmin_crust_mantle,nspec2D_xmax_crust_mantle, &
-                              nspec2D_ymin_crust_mantle,nspec2D_ymax_crust_mantle, &
-                              reclen_xmin_crust_mantle,reclen_xmax_crust_mantle, &
-                              reclen_ymin_crust_mantle,reclen_ymax_crust_mantle, &
-                              nabs_xmin_cm,nabs_xmax_cm,nabs_ymin_cm,nabs_ymax_cm, &
-                              absorb_xmin_crust_mantle5,absorb_xmax_crust_mantle5, &
-                              absorb_ymin_crust_mantle5,absorb_ymax_crust_mantle5)
-    endif ! Stacey conditions
-
-    ! add the sources
-    if (SIMULATION_TYPE == 1) &
-      call compute_add_sources(myrank,NSOURCES, &
-                                accel_crust_mantle,sourcearrays, &
-                                DT,t0,tshift_cmt,hdur_gaussian,ibool_crust_mantle, &
-                                islice_selected_source,ispec_selected_source,it, &
-                                hdur,xi_source,eta_source,gamma_source,nu_source)
-
-    ! add adjoint sources
-    if (SIMULATION_TYPE == 2 .or. SIMULATION_TYPE == 3) then
-      if( nadj_rec_local > 0 ) &
-        call compute_add_sources_adjoint(myrank,nrec, &
-                                nadj_rec_local,NSTEP,NTSTEP_BETWEEN_READ_ADJSRC, &
-                                accel_crust_mantle,adj_sourcearrays, &
-                                nu,xi_receiver,eta_receiver,gamma_receiver, &
-                                xigll,yigll,zigll,ibool_crust_mantle, &
-                                islice_selected_rec,ispec_selected_rec, &
-                                NSTEP_SUB_ADJ,iadjsrc_len,iadjsrc,iadj_vec, &
-                                it,it_begin,station_name,network_name,DT)
-    endif
-
-    ! add sources for backward/reconstructed wavefield
-    if (SIMULATION_TYPE == 3) &
-      call compute_add_sources_backward(myrank,NSOURCES,NSTEP, &
-                                b_accel_crust_mantle,sourcearrays, &
-                                DT,t0,tshift_cmt,hdur_gaussian,ibool_crust_mantle, &
-                                islice_selected_source,ispec_selected_source,it, &
-                                hdur,xi_source,eta_source,gamma_source,nu_source)
-
-!<YANGL
-    ! NOISE_TOMOGRAPHY
-    if ( NOISE_TOMOGRAPHY == 1 ) then
-       ! the first step of noise tomography is to use |S(\omega)|^2 as a point force source at one of the receivers.
-       ! hence, instead of a moment tensor 'sourcearrays', a 'noise_sourcearray' for a point force is needed.
-       ! furthermore, the CMTSOLUTION needs to be zero, i.e., no earthquakes.
-       ! now this must be manually set in DATA/CMTSOLUTION, by USERS.
-       call add_source_master_rec_noise(myrank,nrec, &
-                                NSTEP,accel_crust_mantle,noise_sourcearray, &
-                                ibool_crust_mantle,islice_selected_rec,ispec_selected_rec, &
-                                it,irec_master_noise)
-    elseif ( NOISE_TOMOGRAPHY == 2 ) then
-       ! second step of noise tomography, i.e., read the surface movie saved at every timestep
-       ! use the movie to drive the ensemble forward wavefield
-       call noise_read_add_surface_movie(nmovie_points,accel_crust_mantle, &
-                              normal_x_noise,normal_y_noise,normal_z_noise,mask_noise, &
-                              ibelm_top_crust_mantle,ibool_crust_mantle, &
-                              NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie, &
-                              NSTEP-it+1,jacobian2D_top_crust_mantle,wgllwgll_xy)
-        ! be careful, since ensemble forward sources are reversals of generating wavefield "eta"
-        ! hence the "NSTEP-it+1", i.e., start reading from the last timestep
-        ! note the ensemble forward sources are generally distributed on the surface of the earth
-        ! that's to say, the ensemble forward source is kind of a surface force density, not a body force density
-        ! therefore, we must add it here, before applying the inverse of mass matrix
-    elseif ( NOISE_TOMOGRAPHY == 3 ) then
-        ! third step of noise tomography, i.e., read the surface movie saved at every timestep
-        ! use the movie to reconstruct the ensemble forward wavefield
-        ! the ensemble adjoint wavefield is done as usual
-        ! note instead of "NSTEP-it+1", now we us "it", since reconstruction is a reversal of reversal
-        call noise_read_add_surface_movie(nmovie_points,b_accel_crust_mantle, &
-                              normal_x_noise,normal_y_noise,normal_z_noise,mask_noise, &
-                              ibelm_top_crust_mantle,ibool_crust_mantle, &
-                              NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie, &
-                              it,jacobian2D_top_crust_mantle,wgllwgll_xy)
-    endif
-!>YANGL
-
-    ! ****************************************************
-    ! **********  add matching with fluid part  **********
-    ! ****************************************************
-
-    ! only for elements in first matching layer in the solid
-
-    !---
-    !--- couple with outer core at the bottom of the mantle
-    !---
-    if(ACTUALLY_COUPLE_FLUID_CMB) &
-      call compute_coupling_CMB_fluid(displ_crust_mantle,b_displ_crust_mantle, &
-                            accel_crust_mantle,b_accel_crust_mantle, &
-                            ibool_crust_mantle,ibelm_bottom_crust_mantle,  &
-                            accel_outer_core,b_accel_outer_core, &
-                            normal_top_outer_core,jacobian2D_top_outer_core, &
-                            wgllwgll_xy,ibool_outer_core,ibelm_top_outer_core, &
-                            RHO_TOP_OC,minus_g_cmb, &
-                            SIMULATION_TYPE,NSPEC2D_BOTTOM(IREGION_CRUST_MANTLE))
-
-    !---
-    !--- couple with outer core at the top of the inner core
-    !---
-    if(ACTUALLY_COUPLE_FLUID_ICB) &
-      call compute_coupling_ICB_fluid(displ_inner_core,b_displ_inner_core, &
-                            accel_inner_core,b_accel_inner_core, &
-                            ibool_inner_core,ibelm_top_inner_core,  &
-                            accel_outer_core,b_accel_outer_core, &
-                            normal_bottom_outer_core,jacobian2D_bottom_outer_core, &
-                            wgllwgll_xy,ibool_outer_core,ibelm_bottom_outer_core, &
-                            RHO_BOTTOM_OC,minus_g_icb, &
-                            SIMULATION_TYPE,NSPEC2D_TOP(IREGION_INNER_CORE))
-
-
-    ! assemble all the contributions between slices using MPI
-
-! assemble all the contributions between slices using MPI
-! crust/mantle and inner core handled in the same call
-! in order to reduce the number of MPI messages by 2
-  if(USE_NONBLOCKING_COMMS) then
-
-    iphase = 1 ! initialize the non blocking communication counter
-    iphase_CC = 1 ! initialize the non blocking communication counter for the central cube
-
-! start the non blocking communications
-    call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
-            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,iphase)
-
-    icall = 2 ! now compute all the inner elements in the case of non blocking MPI
-
-    ! compute internal forces in the solid regions
-
-    ! for anisotropy and gravity, x y and z contain r theta and phi
-
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-      call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_crust_mantle,accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,icall, &
-            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT, &
-          hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-      !---idoubling_crust_mantle, &
-          R_memory_crust_mantle,epsilondev_crust_mantle, &
-          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          alphaval,betaval,gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-    else
-      call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_crust_mantle,accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,icall, &
-            accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz, &
-          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-      ! --idoubling_crust_mantle, &
-          R_memory_crust_mantle,epsilondev_crust_mantle, &
-          eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          alphaval,betaval,gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-    endif
-
-    ! Deville routine
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-      call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_inner_core,accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,icall, &
-            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          alphaval,betaval,gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-    else
-      call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          displ_inner_core,accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,icall, &
-            accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector,iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          R_memory_inner_core,epsilondev_inner_core, eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          alphaval,betaval,gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-    endif
-
-! assemble all the contributions between slices using MPI
-! crust/mantle and inner core handled in the same call
-! in order to reduce the number of MPI messages by 2
-    do while (iphase <= 7) ! make sure the last communications are finished and processed
-      call assemble_MPI_vector(myrank,accel_crust_mantle,accel_inner_core, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces,npoin2D_max_all_CM_IC, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
-            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,iphase)
-    enddo
-  else
-    ! crust/mantle and inner core handled in the same call
-    ! in order to reduce the number of MPI messages by 2
-    call assemble_MPI_vector_block(myrank, &
-            accel_crust_mantle,NGLOB_CRUST_MANTLE, &
-            accel_inner_core,NGLOB_INNER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
-            iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core, &
-            iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces,imsg_type, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            buffer_send_faces,buffer_received_faces, &
-            buffer_send_chunkcorn_vector,buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL, &
-            NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_CRUST_MANTLE),NGLOB2DMAX_YMIN_YMAX(IREGION_CRUST_MANTLE), &
-            NGLOB1D_RADIAL(IREGION_INNER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_INNER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_INNER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL)
-  endif
-
-    !---
-    !---  use buffers to assemble forces with the central cube
-    !---
-
-  if(INCLUDE_CENTRAL_CUBE) then
-    if(USE_NONBLOCKING_COMMS) then
-      do while (iphase_CC <= 4) ! make sure the last communications are finished and processed
-        call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-          npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,ibool_central_cube, &
-          receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
-          ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),accel_inner_core,NDIM,iphase_CC)
-      enddo
-    else
-      call assemble_MPI_central_cube_block(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-        npoin2D_cube_from_slices,buffer_all_cube_from_slices,buffer_slices,buffer_slices2,ibool_central_cube, &
-        receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core,NSPEC_INNER_CORE, &
-        ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),NGLOB_INNER_CORE,accel_inner_core,NDIM)
-    endif
-  endif   ! end of assembling forces with the central cube
-
-! way 1:
-!    do i=1,NGLOB_CRUST_MANTLE
-!      accel_crust_mantle(1,i) = accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
-!               + two_omega_earth*veloc_crust_mantle(2,i)
-!      accel_crust_mantle(2,i) = accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
-!               - two_omega_earth*veloc_crust_mantle(1,i)
-!      accel_crust_mantle(3,i) = accel_crust_mantle(3,i)*rmass_crust_mantle(i)
-!    enddo
-
-! way 2:
-    do i=1,mod(NGLOB_CRUST_MANTLE,4)
-      accel_crust_mantle(1,i) = accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
-               + two_omega_earth*veloc_crust_mantle(2,i)
-      accel_crust_mantle(2,i) = accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
-               - two_omega_earth*veloc_crust_mantle(1,i)
-      accel_crust_mantle(3,i) = accel_crust_mantle(3,i)*rmass_crust_mantle(i)
-    enddo
-    do i=mod(NGLOB_CRUST_MANTLE,4)+1,NGLOB_CRUST_MANTLE,4
-      accel_crust_mantle(1,i) = accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
-               + two_omega_earth*veloc_crust_mantle(2,i)
-      accel_crust_mantle(2,i) = accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
-               - two_omega_earth*veloc_crust_mantle(1,i)
-      accel_crust_mantle(3,i) = accel_crust_mantle(3,i)*rmass_crust_mantle(i)
-
-      accel_crust_mantle(1,i+1) = accel_crust_mantle(1,i+1)*rmass_crust_mantle(i+1) &
-               + two_omega_earth*veloc_crust_mantle(2,i+1)
-      accel_crust_mantle(2,i+1) = accel_crust_mantle(2,i+1)*rmass_crust_mantle(i+1) &
-               - two_omega_earth*veloc_crust_mantle(1,i+1)
-      accel_crust_mantle(3,i+1) = accel_crust_mantle(3,i+1)*rmass_crust_mantle(i+1)
-
-      accel_crust_mantle(1,i+2) = accel_crust_mantle(1,i+2)*rmass_crust_mantle(i+2) &
-               + two_omega_earth*veloc_crust_mantle(2,i+2)
-      accel_crust_mantle(2,i+2) = accel_crust_mantle(2,i+2)*rmass_crust_mantle(i+2) &
-               - two_omega_earth*veloc_crust_mantle(1,i+2)
-      accel_crust_mantle(3,i+2) = accel_crust_mantle(3,i+2)*rmass_crust_mantle(i+2)
-
-      accel_crust_mantle(1,i+3) = accel_crust_mantle(1,i+3)*rmass_crust_mantle(i+3) &
-               + two_omega_earth*veloc_crust_mantle(2,i+3)
-      accel_crust_mantle(2,i+3) = accel_crust_mantle(2,i+3)*rmass_crust_mantle(i+3) &
-               - two_omega_earth*veloc_crust_mantle(1,i+3)
-      accel_crust_mantle(3,i+3) = accel_crust_mantle(3,i+3)*rmass_crust_mantle(i+3)
-    enddo
-
-    if (SIMULATION_TYPE == 3) then
-
-! ------------------- new non blocking implementation -------------------
-
-    ! assemble all the contributions between slices using MPI
-
-! assemble all the contributions between slices using MPI
-! crust/mantle and inner core handled in the same call
-! in order to reduce the number of MPI messages by 2
-  if(USE_NONBLOCKING_COMMS) then
-
-    b_iphase = 1 ! initialize the non blocking communication counter
-    b_iphase_CC = 1 ! initialize the non blocking communication counter for the central cube
-
-! start the non blocking communications
-    call assemble_MPI_vector(myrank,b_accel_crust_mantle,b_accel_inner_core, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
-            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,b_iphase)
-
-    b_icall = 2 ! now compute all the inner elements in the case of non blocking MPI
-
-    ! compute internal forces in the solid regions
-
-    ! for anisotropy and gravity, x y and z contain r theta and phi
-
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-      call compute_forces_crust_mantle_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_crust_mantle,b_accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,b_icall, &
-            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT, &
-          hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-      ! --idoubling_crust_mantle, &
-          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
-          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-    else
-      call compute_forces_crust_mantle(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_crust_mantle,b_accel_crust_mantle, &
-          xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-          xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-          etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-          gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-!----------------------
-            is_on_a_slice_edge_crust_mantle,b_icall, &
-            b_accel_inner_core,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz, &
-          hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_crust_mantle,kappahstore_crust_mantle,muvstore_crust_mantle, &
-          muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-          c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle, &
-          c14store_crust_mantle,c15store_crust_mantle,c16store_crust_mantle, &
-          c22store_crust_mantle,c23store_crust_mantle,c24store_crust_mantle, &
-          c25store_crust_mantle,c26store_crust_mantle,c33store_crust_mantle, &
-          c34store_crust_mantle,c35store_crust_mantle,c36store_crust_mantle, &
-          c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-          c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-          ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-      !--idoubling_crust_mantle, &
-          b_R_memory_crust_mantle,b_epsilondev_crust_mantle, &
-          b_eps_trace_over_3_crust_mantle,one_minus_sum_beta_crust_mantle, &
-          b_alphaval,b_betaval,b_gammaval,factor_common_crust_mantle, &
-          size(factor_common_crust_mantle,2), size(factor_common_crust_mantle,3), &
-          size(factor_common_crust_mantle,4), size(factor_common_crust_mantle,5) )
-    endif
-
-    ! Deville routine
-    if( USE_DEVILLE_PRODUCTS_VAL ) then
-      call compute_forces_inner_core_Dev(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_inner_core,b_accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,b_icall, &
-            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_xxT,hprimewgll_xx,hprimewgll_xxT, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          b_alphaval,b_betaval,b_gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-    else
-      call compute_forces_inner_core(minus_gravity_table,density_table,minus_deriv_gravity_table, &
-          b_displ_inner_core,b_accel_inner_core, &
-          xstore_inner_core,ystore_inner_core,zstore_inner_core, &
-          xix_inner_core,xiy_inner_core,xiz_inner_core, &
-          etax_inner_core,etay_inner_core,etaz_inner_core, &
-          gammax_inner_core,gammay_inner_core,gammaz_inner_core, &
-!----------------------
-            is_on_a_slice_edge_inner_core,b_icall, &
-            b_accel_crust_mantle,ibool_inner_core,idoubling_inner_core, &
-            myrank,iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector,b_iphase, &
-            nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-            npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-            receiver_cube_from_slices,ibelm_bottom_inner_core,NSPEC2D_BOTTOM_IC,INCLUDE_CENTRAL_CUBE,b_iphase_CC, &
-!----------------------
-          hprime_xx,hprime_yy,hprime_zz,hprimewgll_xx,hprimewgll_yy,hprimewgll_zz, &
-          wgllwgll_xy,wgllwgll_xz,wgllwgll_yz,wgll_cube, &
-          kappavstore_inner_core,muvstore_inner_core,ibool_inner_core,idoubling_inner_core, &
-          c11store_inner_core,c33store_inner_core,c12store_inner_core, &
-          c13store_inner_core,c44store_inner_core, &
-          b_R_memory_inner_core,b_epsilondev_inner_core, b_eps_trace_over_3_inner_core,&
-          one_minus_sum_beta_inner_core, &
-          b_alphaval,b_betaval,b_gammaval, &
-          factor_common_inner_core, &
-          size(factor_common_inner_core,2), size(factor_common_inner_core,3), &
-          size(factor_common_inner_core,4), size(factor_common_inner_core,5) )
-    endif
-
-! assemble all the contributions between slices using MPI
-! crust/mantle and inner core handled in the same call
-! in order to reduce the number of MPI messages by 2
-    do while (b_iphase <= 7) ! make sure the last communications are finished and processed
-      call assemble_MPI_vector(myrank,b_accel_crust_mantle,b_accel_inner_core, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle,iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core,iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces,npoin2D_max_all_CM_IC, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL,NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
-            NGLOB1D_RADIAL(IREGION_INNER_CORE),NCHUNKS_VAL,b_iphase)
-    enddo
-  else
-    ! crust/mantle and inner core handled in the same call
-    ! in order to reduce the number of MPI messages by 2
-    call assemble_MPI_vector_block(myrank, &
-            b_accel_crust_mantle,NGLOB_CRUST_MANTLE, &
-            b_accel_inner_core,NGLOB_INNER_CORE, &
-            iproc_xi,iproc_eta,ichunk,addressing, &
-            iboolleft_xi_crust_mantle,iboolright_xi_crust_mantle, &
-            iboolleft_eta_crust_mantle,iboolright_eta_crust_mantle, &
-            npoin2D_faces_crust_mantle,npoin2D_xi_crust_mantle,npoin2D_eta_crust_mantle, &
-            iboolfaces_crust_mantle,iboolcorner_crust_mantle, &
-            iboolleft_xi_inner_core,iboolright_xi_inner_core, &
-            iboolleft_eta_inner_core,iboolright_eta_inner_core, &
-            npoin2D_faces_inner_core,npoin2D_xi_inner_core,npoin2D_eta_inner_core, &
-            iboolfaces_inner_core,iboolcorner_inner_core, &
-            iprocfrom_faces,iprocto_faces,imsg_type, &
-            iproc_master_corners,iproc_worker1_corners,iproc_worker2_corners, &
-            b_buffer_send_faces,b_buffer_received_faces, &
-            b_buffer_send_chunkcorn_vector,b_buffer_recv_chunkcorn_vector, &
-            NUMMSGS_FACES,NUM_MSG_TYPES,NCORNERSCHUNKS, &
-            NPROC_XI_VAL,NPROC_ETA_VAL, &
-            NGLOB1D_RADIAL(IREGION_CRUST_MANTLE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_CRUST_MANTLE),NGLOB2DMAX_YMIN_YMAX(IREGION_CRUST_MANTLE), &
-            NGLOB1D_RADIAL(IREGION_INNER_CORE), &
-            NGLOB2DMAX_XMIN_XMAX(IREGION_INNER_CORE),NGLOB2DMAX_YMIN_YMAX(IREGION_INNER_CORE), &
-            NGLOB2DMAX_XY,NCHUNKS_VAL)
-  endif
-
-    !---
-    !---  use buffers to assemble forces with the central cube
-    !---
-
-  if(INCLUDE_CENTRAL_CUBE) then
-    if(USE_NONBLOCKING_COMMS) then
-      do while (b_iphase_CC <= 4) ! make sure the last communications are finished and processed
-        call assemble_MPI_central_cube(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-          npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,ibool_central_cube, &
-          receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core, &
-          ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),b_accel_inner_core,NDIM,b_iphase_CC)
-      enddo
-    else
-      call assemble_MPI_central_cube_block(ichunk,nb_msgs_theor_in_cube,sender_from_slices_to_cube, &
-        npoin2D_cube_from_slices,b_buffer_all_cube_from_slices,b_buffer_slices,buffer_slices2,ibool_central_cube, &
-        receiver_cube_from_slices,ibool_inner_core,idoubling_inner_core,NSPEC_INNER_CORE, &
-        ibelm_bottom_inner_core,NSPEC2D_BOTTOM(IREGION_INNER_CORE),NGLOB_INNER_CORE,b_accel_inner_core,NDIM)
-    endif
-  endif   ! end of assembling forces with the central cube
-
-! ------------------- new non blocking implementation -------------------
-
-! way 1:
-!      do i=1,NGLOB_CRUST_MANTLE
-!        b_accel_crust_mantle(1,i) = b_accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
-!                 + b_two_omega_earth*b_veloc_crust_mantle(2,i)
-!        b_accel_crust_mantle(2,i) = b_accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
-!                 - b_two_omega_earth*b_veloc_crust_mantle(1,i)
-!        b_accel_crust_mantle(3,i) = b_accel_crust_mantle(3,i)*rmass_crust_mantle(i)
-!      enddo
-
-! way 2:
-      do i=1,mod(NGLOB_CRUST_MANTLE,4)
-        b_accel_crust_mantle(1,i) = b_accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
-                 + b_two_omega_earth*b_veloc_crust_mantle(2,i)
-        b_accel_crust_mantle(2,i) = b_accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
-                 - b_two_omega_earth*b_veloc_crust_mantle(1,i)
-        b_accel_crust_mantle(3,i) = b_accel_crust_mantle(3,i)*rmass_crust_mantle(i)
-      enddo
-      do i=mod(NGLOB_CRUST_MANTLE,4)+1,NGLOB_CRUST_MANTLE,4
-        b_accel_crust_mantle(1,i) = b_accel_crust_mantle(1,i)*rmass_crust_mantle(i) &
-                 + b_two_omega_earth*b_veloc_crust_mantle(2,i)
-        b_accel_crust_mantle(2,i) = b_accel_crust_mantle(2,i)*rmass_crust_mantle(i) &
-                 - b_two_omega_earth*b_veloc_crust_mantle(1,i)
-        b_accel_crust_mantle(3,i) = b_accel_crust_mantle(3,i)*rmass_crust_mantle(i)
-
-        b_accel_crust_mantle(1,i+1) = b_accel_crust_mantle(1,i+1)*rmass_crust_mantle(i+1) &
-                 + b_two_omega_earth*b_veloc_crust_mantle(2,i+1)
-        b_accel_crust_mantle(2,i+1) = b_accel_crust_mantle(2,i+1)*rmass_crust_mantle(i+1) &
-                 - b_two_omega_earth*b_veloc_crust_mantle(1,i+1)
-        b_accel_crust_mantle(3,i+1) = b_accel_crust_mantle(3,i+1)*rmass_crust_mantle(i+1)
-
-        b_accel_crust_mantle(1,i+2) = b_accel_crust_mantle(1,i+2)*rmass_crust_mantle(i+2) &
-                 + b_two_omega_earth*b_veloc_crust_mantle(2,i+2)
-        b_accel_crust_mantle(2,i+2) = b_accel_crust_mantle(2,i+2)*rmass_crust_mantle(i+2) &
-                 - b_two_omega_earth*b_veloc_crust_mantle(1,i+2)
-        b_accel_crust_mantle(3,i+2) = b_accel_crust_mantle(3,i+2)*rmass_crust_mantle(i+2)
-
-        b_accel_crust_mantle(1,i+3) = b_accel_crust_mantle(1,i+3)*rmass_crust_mantle(i+3) &
-                 + b_two_omega_earth*b_veloc_crust_mantle(2,i+3)
-        b_accel_crust_mantle(2,i+3) = b_accel_crust_mantle(2,i+3)*rmass_crust_mantle(i+3) &
-                 - b_two_omega_earth*b_veloc_crust_mantle(1,i+3)
-        b_accel_crust_mantle(3,i+3) = b_accel_crust_mantle(3,i+3)*rmass_crust_mantle(i+3)
-      enddo
-
-    endif
-
-    ! couples ocean with crust mantle
-    if(OCEANS_VAL) &
-      call compute_coupling_ocean(accel_crust_mantle,b_accel_crust_mantle, &
-                            rmass_crust_mantle,rmass_ocean_load,normal_top_crust_mantle, &
-                            ibool_crust_mantle,ibelm_top_crust_mantle, &
-                            updated_dof_ocean_load, &
-                            SIMULATION_TYPE,NSPEC2D_TOP(IREGION_CRUST_MANTLE))
-
-
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-
-! way 1:
-!    do i=1,NGLOB_CRUST_MANTLE
-!      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) + deltatover2*accel_crust_mantle(:,i)
-!    enddo
-!
-!    do i=1,NGLOB_INNER_CORE
-!      accel_inner_core(1,i) = accel_inner_core(1,i)*rmass_inner_core(i) &
-!             + two_omega_earth*veloc_inner_core(2,i)
-!      accel_inner_core(2,i) = accel_inner_core(2,i)*rmass_inner_core(i) &
-!             - two_omega_earth*veloc_inner_core(1,i)
-!      accel_inner_core(3,i) = accel_inner_core(3,i)*rmass_inner_core(i)
-!
-!      veloc_inner_core(:,i) = veloc_inner_core(:,i) + deltatover2*accel_inner_core(:,i)
-!    enddo
-
-! way 2:
-    do i=1,mod(NGLOB_CRUST_MANTLE,4)
-      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) + deltatover2*accel_crust_mantle(:,i)
-    enddo
-    do i=mod(NGLOB_CRUST_MANTLE,4)+1,NGLOB_CRUST_MANTLE,4
-      veloc_crust_mantle(:,i) = veloc_crust_mantle(:,i) + deltatover2*accel_crust_mantle(:,i)
-      veloc_crust_mantle(:,i+1) = veloc_crust_mantle(:,i+1) + deltatover2*accel_crust_mantle(:,i+1)
-      veloc_crust_mantle(:,i+2) = veloc_crust_mantle(:,i+2) + deltatover2*accel_crust_mantle(:,i+2)
-      veloc_crust_mantle(:,i+3) = veloc_crust_mantle(:,i+3) + deltatover2*accel_crust_mantle(:,i+3)
-    enddo
-
-    if(imodulo_NGLOB_INNER_CORE >= 1) then
-      do i=1,imodulo_NGLOB_INNER_CORE
-        accel_inner_core(1,i) = accel_inner_core(1,i)*rmass_inner_core(i) &
-               + two_omega_earth*veloc_inner_core(2,i)
-        accel_inner_core(2,i) = accel_inner_core(2,i)*rmass_inner_core(i) &
-               - two_omega_earth*veloc_inner_core(1,i)
-        accel_inner_core(3,i) = accel_inner_core(3,i)*rmass_inner_core(i)
-
-        veloc_inner_core(:,i) = veloc_inner_core(:,i) + deltatover2*accel_inner_core(:,i)
-    enddo
-    endif
-    do i=imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE,3
-      accel_inner_core(1,i) = accel_inner_core(1,i)*rmass_inner_core(i) &
-             + two_omega_earth*veloc_inner_core(2,i)
-      accel_inner_core(2,i) = accel_inner_core(2,i)*rmass_inner_core(i) &
-             - two_omega_earth*veloc_inner_core(1,i)
-      accel_inner_core(3,i) = accel_inner_core(3,i)*rmass_inner_core(i)
-
-      accel_inner_core(1,i+1) = accel_inner_core(1,i+1)*rmass_inner_core(i+1) &
-             + two_omega_earth*veloc_inner_core(2,i+1)
-      accel_inner_core(2,i+1) = accel_inner_core(2,i+1)*rmass_inner_core(i+1) &
-             - two_omega_earth*veloc_inner_core(1,i+1)
-      accel_inner_core(3,i+1) = accel_inner_core(3,i+1)*rmass_inner_core(i+1)
-
-      accel_inner_core(1,i+2) = accel_inner_core(1,i+2)*rmass_inner_core(i+2) &
-             + two_omega_earth*veloc_inner_core(2,i+2)
-      accel_inner_core(2,i+2) = accel_inner_core(2,i+2)*rmass_inner_core(i+2) &
-             - two_omega_earth*veloc_inner_core(1,i+2)
-      accel_inner_core(3,i+2) = accel_inner_core(3,i+2)*rmass_inner_core(i+2)
-
-      veloc_inner_core(:,i) = veloc_inner_core(:,i) + deltatover2*accel_inner_core(:,i)
-      veloc_inner_core(:,i+1) = veloc_inner_core(:,i+1) + deltatover2*accel_inner_core(:,i+1)
-      veloc_inner_core(:,i+2) = veloc_inner_core(:,i+2) + deltatover2*accel_inner_core(:,i+2)
-    enddo
-
-    if (SIMULATION_TYPE == 3) then
-! way 1:
-!      do i=1,NGLOB_CRUST_MANTLE
-!        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) + b_deltatover2*b_accel_crust_mantle(:,i)
-!      enddo
-!
-!      do i=1,NGLOB_INNER_CORE
-!        b_accel_inner_core(1,i) = b_accel_inner_core(1,i)*rmass_inner_core(i) &
-!         + b_two_omega_earth*b_veloc_inner_core(2,i)
-!        b_accel_inner_core(2,i) = b_accel_inner_core(2,i)*rmass_inner_core(i) &
-!         - b_two_omega_earth*b_veloc_inner_core(1,i)
-!        b_accel_inner_core(3,i) = b_accel_inner_core(3,i)*rmass_inner_core(i)
-!
-!        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) + b_deltatover2*b_accel_inner_core(:,i)
-!      enddo
-
-! way 2:
-      do i=1,mod(NGLOB_CRUST_MANTLE,4)
-        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) + b_deltatover2*b_accel_crust_mantle(:,i)
-      enddo
-      do i=mod(NGLOB_CRUST_MANTLE,4)+1,NGLOB_CRUST_MANTLE,4
-        b_veloc_crust_mantle(:,i) = b_veloc_crust_mantle(:,i) + b_deltatover2*b_accel_crust_mantle(:,i)
-        b_veloc_crust_mantle(:,i+1) = b_veloc_crust_mantle(:,i+1) + b_deltatover2*b_accel_crust_mantle(:,i+1)
-        b_veloc_crust_mantle(:,i+2) = b_veloc_crust_mantle(:,i+2) + b_deltatover2*b_accel_crust_mantle(:,i+2)
-        b_veloc_crust_mantle(:,i+3) = b_veloc_crust_mantle(:,i+3) + b_deltatover2*b_accel_crust_mantle(:,i+3)
-      enddo
-
-    if(imodulo_NGLOB_INNER_CORE >= 1) then
-      do i=1,imodulo_NGLOB_INNER_CORE
-        b_accel_inner_core(1,i) = b_accel_inner_core(1,i)*rmass_inner_core(i) &
-         + b_two_omega_earth*b_veloc_inner_core(2,i)
-        b_accel_inner_core(2,i) = b_accel_inner_core(2,i)*rmass_inner_core(i) &
-         - b_two_omega_earth*b_veloc_inner_core(1,i)
-        b_accel_inner_core(3,i) = b_accel_inner_core(3,i)*rmass_inner_core(i)
-
-        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) + b_deltatover2*b_accel_inner_core(:,i)
-      enddo
-    endif
-      do i=imodulo_NGLOB_INNER_CORE+1,NGLOB_INNER_CORE,3
-        b_accel_inner_core(1,i) = b_accel_inner_core(1,i)*rmass_inner_core(i) &
-         + b_two_omega_earth*b_veloc_inner_core(2,i)
-        b_accel_inner_core(2,i) = b_accel_inner_core(2,i)*rmass_inner_core(i) &
-         - b_two_omega_earth*b_veloc_inner_core(1,i)
-        b_accel_inner_core(3,i) = b_accel_inner_core(3,i)*rmass_inner_core(i)
-
-        b_accel_inner_core(1,i+1) = b_accel_inner_core(1,i+1)*rmass_inner_core(i+1) &
-         + b_two_omega_earth*b_veloc_inner_core(2,i+1)
-        b_accel_inner_core(2,i+1) = b_accel_inner_core(2,i+1)*rmass_inner_core(i+1) &
-         - b_two_omega_earth*b_veloc_inner_core(1,i+1)
-        b_accel_inner_core(3,i+1) = b_accel_inner_core(3,i+1)*rmass_inner_core(i+1)
-
-        b_accel_inner_core(1,i+2) = b_accel_inner_core(1,i+2)*rmass_inner_core(i+2) &
-         + b_two_omega_earth*b_veloc_inner_core(2,i+2)
-        b_accel_inner_core(2,i+2) = b_accel_inner_core(2,i+2)*rmass_inner_core(i+2) &
-         - b_two_omega_earth*b_veloc_inner_core(1,i+2)
-        b_accel_inner_core(3,i+2) = b_accel_inner_core(3,i+2)*rmass_inner_core(i+2)
-
-        b_veloc_inner_core(:,i) = b_veloc_inner_core(:,i) + b_deltatover2*b_accel_inner_core(:,i)
-        b_veloc_inner_core(:,i+1) = b_veloc_inner_core(:,i+1) + b_deltatover2*b_accel_inner_core(:,i+1)
-        b_veloc_inner_core(:,i+2) = b_veloc_inner_core(:,i+2) + b_deltatover2*b_accel_inner_core(:,i+2)
-      enddo
-
-    endif
-
-
-    ! restores last time snapshot saved for backward/reconstruction of wavefields
-    ! note: this is done here after the Newmark time scheme, otherwise the indexing for sources
-    !          and adjoint sources will become more complicated
-    !          that is, index it for adjoint sources will match index NSTEP - 1 for backward/reconstructed wavefields
-    if( SIMULATION_TYPE == 3 .and. it == 1 ) then
-      call read_forward_arrays(myrank, &
-                    b_displ_crust_mantle,b_veloc_crust_mantle,b_accel_crust_mantle, &
-                    b_displ_inner_core,b_veloc_inner_core,b_accel_inner_core, &
-                    b_displ_outer_core,b_veloc_outer_core,b_accel_outer_core, &
-                    b_R_memory_crust_mantle,b_R_memory_inner_core, &
-                    b_epsilondev_crust_mantle,b_epsilondev_inner_core, &
-                    b_A_array_rotation,b_B_array_rotation,LOCAL_PATH)
-    endif
-
-! write the seismograms with time shift
-
-! store the seismograms only if there is at least one receiver located in this slice
-  if (nrec_local > 0) then
-    if (SIMULATION_TYPE == 1) then
-      call compute_seismograms(nrec_local,nrec,displ_crust_mantle, &
-                                nu,hxir_store,hetar_store,hgammar_store, &
-                                scale_displ,ibool_crust_mantle, &
-                                ispec_selected_rec,number_receiver_global, &
-                                seismo_current,NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
-                                seismograms)
-
-    else if (SIMULATION_TYPE == 2) then
-      call compute_seismograms_adjoint(NSOURCES,nrec_local,displ_crust_mantle, &
-                    eps_trace_over_3_crust_mantle,epsilondev_crust_mantle, &
-                    nu_source,Mxx,Myy,Mzz,Mxy,Mxz,Myz, &
-                    hxir_store,hetar_store,hgammar_store, &
-                    hpxir_store,hpetar_store,hpgammar_store, &
-                    tshift_cmt,hdur_gaussian,DT,t0,scale_displ, &
-                    hprime_xx,hprime_yy,hprime_zz, &
-                    xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                    etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle, &
-                    gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle, &
-                    moment_der,sloc_der,stshift_der,shdur_der, &
-                    NTSTEP_BETWEEN_OUTPUT_SEISMOS,seismograms,deltat, &
-                    ibool_crust_mantle,ispec_selected_source,number_receiver_global, &
-                    NSTEP,it,nit_written)
-
-    else if (SIMULATION_TYPE == 3) then
-      call compute_seismograms_backward(nrec_local,nrec,b_displ_crust_mantle, &
-                                nu,hxir_store,hetar_store,hgammar_store, &
-                                scale_displ,ibool_crust_mantle, &
-                                ispec_selected_rec,number_receiver_global, &
-                                seismo_current,NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
-                                seismograms)
-
-    endif
-  endif ! nrec_local
-
-  ! write the current or final seismograms
-  if(seismo_current == NTSTEP_BETWEEN_OUTPUT_SEISMOS .or. it == it_end) then
-    if (SIMULATION_TYPE == 1 .or. SIMULATION_TYPE == 3) then
-      call write_seismograms(myrank,seismograms,number_receiver_global,station_name, &
-            network_name,stlat,stlon,stele,stbur, &
-            nrec,nrec_local,ANGULAR_WIDTH_XI_IN_DEGREES,NEX_XI,DT,t0,it_end, &
-            yr_SAC,jda_SAC,ho_SAC,mi_SAC,sec_SAC,t_cmt_SAC,t_shift_SAC, &
-            elat_SAC,elon_SAC,depth_SAC,event_name_SAC,cmt_lat_SAC,cmt_lon_SAC,&
-            cmt_depth_SAC,cmt_hdur_SAC,NPROCTOT_VAL, &
-            OUTPUT_SEISMOS_ASCII_TEXT,OUTPUT_SEISMOS_SAC_ALPHANUM, &
-            OUTPUT_SEISMOS_SAC_BINARY,ROTATE_SEISMOGRAMS_RT,NTSTEP_BETWEEN_OUTPUT_SEISMOS, &
-            seismo_offset,seismo_current,WRITE_SEISMOGRAMS_BY_MASTER, &
-            SAVE_ALL_SEISMOS_IN_ONE_FILE,USE_BINARY_FOR_LARGE_FILE)
-      if(myrank==0) then
-        write(IMAIN,*)
-        write(IMAIN,*) ' Total number of time steps written: ', it-it_begin+1
-        write(IMAIN,*)
-      endif
-    else
-      if( nrec_local > 0 ) &
-        call write_adj_seismograms(seismograms,number_receiver_global, &
-                                  nrec_local,it,nit_written,DT, &
-                                  NSTEP,NTSTEP_BETWEEN_OUTPUT_SEISMOS,t0,LOCAL_PATH)
-        nit_written = it
-    endif
-    seismo_offset = seismo_offset + seismo_current
-    seismo_current = 0
-  endif
-
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-
-! kernel calculations
-  if (SIMULATION_TYPE == 3) then
-    ! crust mantle
-    call compute_kernels_crust_mantle(ibool_crust_mantle, &
-                          rho_kl_crust_mantle,beta_kl_crust_mantle, &
-                          alpha_kl_crust_mantle,cijkl_kl_crust_mantle, &
-                          accel_crust_mantle,b_displ_crust_mantle, &
-                          epsilondev_crust_mantle,b_epsilondev_crust_mantle, &
-                          eps_trace_over_3_crust_mantle,b_eps_trace_over_3_crust_mantle, &
-                          deltat)
-
-    ! outer core
-    call compute_kernels_outer_core(ibool_outer_core, &
-                        xix_outer_core,xiy_outer_core,xiz_outer_core, &
-                        etax_outer_core,etay_outer_core,etaz_outer_core, &
-                        gammax_outer_core,gammay_outer_core,gammaz_outer_core, &
-                        hprime_xx,hprime_yy,hprime_zz, &
-                        displ_outer_core,accel_outer_core, &
-                        b_displ_outer_core,b_accel_outer_core, &
-                        vector_accel_outer_core,vector_displ_outer_core, &
-                        b_vector_displ_outer_core, &
-                        div_displ_outer_core,b_div_displ_outer_core, &
-                        rhostore_outer_core,kappavstore_outer_core, &
-                        rho_kl_outer_core,alpha_kl_outer_core, &
-                        deviatoric_outercore,nspec_beta_kl_outer_core,beta_kl_outer_core, &
-                        deltat)
-
-    ! inner core
-    call compute_kernels_inner_core(ibool_inner_core, &
-                          rho_kl_inner_core,beta_kl_inner_core, &
-                          alpha_kl_inner_core, &
-                          accel_inner_core,b_displ_inner_core, &
-                          epsilondev_inner_core,b_epsilondev_inner_core, &
-                          eps_trace_over_3_inner_core,b_eps_trace_over_3_inner_core, &
-                          deltat)
-
-!<YANGL
-    ! NOISE TOMOGRAPHY --- source strength kernel
-    if (NOISE_TOMOGRAPHY == 3)  &
-       call compute_kernels_strength_noise(nmovie_points,ibool_crust_mantle, &
-                          Sigma_kl_crust_mantle,displ_crust_mantle,deltat,it, &
-                          normal_x_noise,normal_y_noise,normal_z_noise, &
-                          NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie, &
-                          ibelm_top_crust_mantle)
-!>YANGL
-
-    ! --- boundary kernels ------
-    if (SAVE_BOUNDARY_MESH) then
-      fluid_solid_boundary = .false.
-      iregion_code = IREGION_CRUST_MANTLE
-
-      ! Moho
-      if (.not. SUPPRESS_CRUSTAL_MESH .and. HONOR_1D_SPHERICAL_MOHO) then
-        call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
-                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
-                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-            ! -- idoubling_crust_mantle, &
-                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
-                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
-                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
-                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
-                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
-                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
-                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-                 k_top,ibelm_moho_top,normal_moho,moho_kl_top,fluid_solid_boundary,NSPEC2D_MOHO)
-
-        call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
-                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
-                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-              ! --idoubling_crust_mantle, &
-                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
-                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
-                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
-                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
-                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
-                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
-                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-                 k_bot,ibelm_moho_bot,normal_moho,moho_kl_bot,fluid_solid_boundary,NSPEC2D_MOHO)
-
-        moho_kl = moho_kl + (moho_kl_top - moho_kl_bot) * deltat
-      endif
-
-      ! 400
-      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
-                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
-                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-            ! --idoubling_crust_mantle, &
-                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
-                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
-                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
-                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
-                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
-                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
-                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-                 k_top,ibelm_400_top,normal_400,d400_kl_top,fluid_solid_boundary,NSPEC2D_400)
-
-      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
-                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
-                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-              ! --idoubling_crust_mantle, &
-                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
-                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
-                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
-                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
-                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
-                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
-                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-                 k_bot,ibelm_400_bot,normal_400,d400_kl_bot,fluid_solid_boundary,NSPEC2D_400)
-
-      d400_kl = d400_kl + (d400_kl_top - d400_kl_bot) * deltat
-
-      ! 670
-      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
-                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
-                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-              ! --idoubling_crust_mantle, &
-                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
-                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
-                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
-                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
-                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
-                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
-                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-                 k_top,ibelm_670_top,normal_670,d670_kl_top,fluid_solid_boundary,NSPEC2D_670)
-
-      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
-                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
-                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-              ! --idoubling_crust_mantle, &
-                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
-                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_crust_mantle,kappavstore_crust_mantle,muvstore_crust_mantle, &
-                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
-                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
-                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
-                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
-                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-                 k_bot,ibelm_670_bot,normal_670,d670_kl_bot,fluid_solid_boundary,NSPEC2D_670)
-
-      d670_kl = d670_kl + (d670_kl_top - d670_kl_bot) * deltat
-
-      ! CMB
-      fluid_solid_boundary = .true.
-      iregion_code = IREGION_CRUST_MANTLE
-      call compute_boundary_kernel(displ_crust_mantle,accel_crust_mantle, &
-                 b_displ_crust_mantle,nspec_crust_mantle,iregion_code, &
-                 ystore_crust_mantle,zstore_crust_mantle,ibool_crust_mantle,ispec_is_tiso_crust_mantle, &
-              ! -- idoubling_crust_mantle, &
-                 xix_crust_mantle,xiy_crust_mantle,xiz_crust_mantle, &
-                 etax_crust_mantle,etay_crust_mantle,etaz_crust_mantle,&
-                 gammax_crust_mantle,gammay_crust_mantle,gammaz_crust_mantle,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_crust_mantle,kappavstore_crust_mantle, muvstore_crust_mantle, &
-                 kappahstore_crust_mantle,muhstore_crust_mantle,eta_anisostore_crust_mantle, &
-                 c11store_crust_mantle,c12store_crust_mantle,c13store_crust_mantle,c14store_crust_mantle, &
-                 c15store_crust_mantle,c16store_crust_mantle,c22store_crust_mantle, &
-                 c23store_crust_mantle,c24store_crust_mantle,c25store_crust_mantle,c26store_crust_mantle, &
-                 c33store_crust_mantle,c34store_crust_mantle,c35store_crust_mantle, &
-                 c36store_crust_mantle,c44store_crust_mantle,c45store_crust_mantle,c46store_crust_mantle, &
-                 c55store_crust_mantle,c56store_crust_mantle,c66store_crust_mantle, &
-                 k_top,ibelm_bottom_crust_mantle,normal_top_outer_core, &
-                 cmb_kl_top,fluid_solid_boundary,NSPEC2D_CMB)
-
-      iregion_code = IREGION_OUTER_CORE
-      call compute_boundary_kernel(vector_displ_outer_core,vector_accel_outer_core, &
-                 b_vector_displ_outer_core,nspec_outer_core, &
-                 iregion_code,ystore_outer_core,zstore_outer_core,ibool_outer_core,ispec_is_tiso_outer_core, &
-              ! --idoubling_outer_core, &
-                 xix_outer_core,xiy_outer_core,xiz_outer_core, &
-                 etax_outer_core,etay_outer_core,etaz_outer_core,&
-                 gammax_outer_core,gammay_outer_core,gammaz_outer_core,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_outer_core,kappavstore_outer_core,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 k_bot,ibelm_top_outer_core,normal_top_outer_core, &
-                 cmb_kl_bot,fluid_solid_boundary,NSPEC2D_CMB)
-
-      cmb_kl = cmb_kl + (cmb_kl_top - cmb_kl_bot) * deltat
-
-      ! ICB
-      fluid_solid_boundary = .true.
-      call compute_boundary_kernel(vector_displ_outer_core,vector_accel_outer_core, &
-                 b_vector_displ_outer_core,nspec_outer_core, &
-                 iregion_code,ystore_outer_core,zstore_outer_core,ibool_outer_core,ispec_is_tiso_outer_core, &
-              ! --idoubling_outer_core, &
-                 xix_outer_core,xiy_outer_core,xiz_outer_core, &
-                 etax_outer_core,etay_outer_core,etaz_outer_core,&
-                 gammax_outer_core,gammay_outer_core,gammaz_outer_core,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_outer_core,kappavstore_outer_core,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 k_top,ibelm_bottom_outer_core,normal_bottom_outer_core, &
-                 icb_kl_top,fluid_solid_boundary,NSPEC2D_ICB)
-
-      iregion_code = IREGION_INNER_CORE
-      call compute_boundary_kernel(displ_inner_core,accel_inner_core, &
-                 b_displ_inner_core,nspec_inner_core,iregion_code, &
-                 ystore_inner_core,zstore_inner_core,ibool_inner_core,ispec_is_tiso_inner_core, &
-              ! -- idoubling_inner_core, &
-                 xix_inner_core,xiy_inner_core,xiz_inner_core, &
-                 etax_inner_core,etay_inner_core,etaz_inner_core,&
-                 gammax_inner_core,gammay_inner_core,gammaz_inner_core,hprime_xx,hprime_yy,hprime_zz, &
-                 rhostore_inner_core,kappavstore_inner_core,muvstore_inner_core, &
-                 dummy_array,dummy_array,dummy_array, &
-                 c11store_inner_core,c12store_inner_core,c13store_inner_core,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array,dummy_array, &
-                 c33store_inner_core,dummy_array,dummy_array, &
-                 dummy_array,c44store_inner_core,dummy_array,dummy_array, &
-                 dummy_array,dummy_array,dummy_array, &
-                 k_bot,ibelm_top_inner_core,normal_bottom_outer_core, &
-                 icb_kl_bot,fluid_solid_boundary,NSPEC2D_ICB)
-
-      icb_kl = icb_kl + (icb_kl_top - icb_kl_bot) * deltat
-    endif
-
-    ! approximate hessian
-    if( APPROXIMATE_HESS_KL ) then
-      call compute_kernels_hessian(ibool_crust_mantle, &
-                          hess_kl_crust_mantle,&
-                          accel_crust_mantle,b_accel_crust_mantle, &
-                          deltat)
-    endif
-
-  endif ! end computing kernels
-
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-
-!<YANGL
-  ! first step of noise tomography, i.e., save a surface movie at every time step
-  ! modified from the subroutine 'write_movie_surface'
-  if ( NOISE_TOMOGRAPHY == 1 ) then
-        call noise_save_surface_movie(displ_crust_mantle, &
-                            ibelm_top_crust_mantle,ibool_crust_mantle, &
-                            NSPEC2D_TOP(IREGION_CRUST_MANTLE),noise_surface_movie,it)
-  endif
-!>YANGL
-
-  ! save movie on surface
-  if( MOVIE_SURFACE ) then
-    if( mod(it,NTSTEP_BETWEEN_FRAMES) == 0) then
-      ! save velocity here to avoid static offset on displacement for movies
-      call write_movie_surface(myrank,nmovie_points,scale_veloc,veloc_crust_mantle, &
-                    scale_displ,displ_crust_mantle, &
-                    xstore_crust_mantle,ystore_crust_mantle,zstore_crust_mantle, &
-                    store_val_x,store_val_y,store_val_z, &
-                    store_val_x_all,store_val_y_all,store_val_z_all, &
-                    store_val_ux,store_val_uy,store_val_uz, &
-                    store_val_ux_all,store_val_uy_all,store_val_uz_all, &
-                    ibelm_top_crust_mantle,ibool_crust_mantle, &
-                    NSPEC2D_TOP(IREGION_CRUST_MANTLE), &
-                    NIT,it,OUTPUT_FILES,MOVIE_VOLUME_TYPE)
-    endif
-  endif
-
-
-  ! save movie in full 3D mesh
-  if(MOVIE_VOLUME ) then
-    if( mod(it-MOVIE_START,NTSTEP_BETWEEN_FRAMES) == 0  &
-      .and. it >= MOVIE_START .and. it <= MOVIE_STOP) then
-
-      if (MOVIE_VOLUME_TYPE == 1) then  ! output strains
-
-        call  write_movie_volume_strains(myrank,npoints_3dmovie, &
-                    LOCAL_PATH,MOVIE_VOLUME_TYPE,MOVIE_COARSE, &
-                    it,eps_trace_over_3_crust_mantle,epsilondev_crust_mantle, &
-                    muvstore_crust_mantle_3dmovie, &
-                    mask_3dmovie,nu_3dmovie)
-
-      else if (MOVIE_VOLUME_TYPE == 2 .or. MOVIE_VOLUME_TYPE == 3) then
-        ! output the Time Integral of Strain, or \mu*TIS
-        call  write_movie_volume_strains(myrank,npoints_3dmovie, &
-                    LOCAL_PATH,MOVIE_VOLUME_TYPE,MOVIE_COARSE, &
-                    it,Ieps_trace_over_3_crust_mantle,Iepsilondev_crust_mantle, &
-                    muvstore_crust_mantle_3dmovie, &
-                    mask_3dmovie,nu_3dmovie)
-
-      else if (MOVIE_VOLUME_TYPE == 4) then ! output divergence and curl in whole volume
-
-        call write_movie_volume_divcurl(myrank,it,eps_trace_over_3_crust_mantle,&
-                    div_displ_outer_core,eps_trace_over_3_inner_core,epsilondev_crust_mantle,&
-                    epsilondev_inner_core)
-
-      else if (MOVIE_VOLUME_TYPE == 5) then !output displacement
-        scalingval = scale_displ
-        call write_movie_volume_vector(myrank,it,npoints_3dmovie, &
-                    LOCAL_PATH,MOVIE_VOLUME_TYPE, &
-                    MOVIE_COARSE,ibool_crust_mantle,displ_crust_mantle, &
-                    scalingval,mask_3dmovie,nu_3dmovie)
-
-      else if (MOVIE_VOLUME_TYPE == 6) then !output velocity
-        scalingval = scale_veloc
-        call write_movie_volume_vector(myrank,it,npoints_3dmovie, &
-                    LOCAL_PATH,MOVIE_VOLUME_TYPE, &
-                    MOVIE_COARSE,ibool_crust_mantle,veloc_crust_mantle, &
-                    scalingval,mask_3dmovie,nu_3dmovie)
-
-      else
-
-        stop 'MOVIE_VOLUME_TYPE has to be 1,2,3,4'
-
-      endif ! MOVIE_VOLUME_TYPE
-    endif
-  endif ! MOVIE_VOLUME
-
-!---- end of time iteration loop
-!
-  enddo   ! end of main time loop
-!
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!-------------------------------------------------------------------------------------------------
-!
-
-  ! synchronize all processes, waits until all processes have written their seismograms
-  call MPI_BARRIER(MPI_COMM_WORLD,ier)
-  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize after time loop')
-
-  ! closes Stacey absorbing boundary snapshots
-  if( ABSORBING_CONDITIONS ) then
-    ! crust mantle
-    if (nspec2D_xmin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(0)
-    endif
-
-    if (nspec2D_xmax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(1)
-    endif
-
-    if (nspec2D_ymin_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(2)
-    endif
-
-    if (nspec2D_ymax_crust_mantle > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(3)
-    endif
-
-    ! outer core
-    if (nspec2D_xmin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(4)
-    endif
-
-    if (nspec2D_xmax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(5)
-    endif
-
-    if (nspec2D_ymin_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(6)
-    endif
-
-    if (nspec2D_ymax_outer_core > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(7)
-    endif
-
-    if (NSPEC2D_BOTTOM(IREGION_OUTER_CORE) > 0 .and. (SIMULATION_TYPE == 3 &
-      .or. (SIMULATION_TYPE == 1 .and. SAVE_FORWARD))) then
-      call close_file_abs(8)
-    endif
-
-  endif
-
-  ! save/read the surface movie using the same c routine as we do for absorbing boundaries (file ID is 9)
-  if (NOISE_TOMOGRAPHY/=0) then
-    call close_file_abs(9)
-    deallocate(noise_surface_movie)
-  endif
-
-
-  ! synchronize all processes
-  call MPI_BARRIER(MPI_COMM_WORLD,ier)
-  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize closing snapshots')
-
-  ! save files to local disk or tape system if restart file
-  call save_forward_arrays(myrank,SIMULATION_TYPE,SAVE_FORWARD, &
-                    NUMBER_OF_RUNS,NUMBER_OF_THIS_RUN, &
-                    displ_crust_mantle,veloc_crust_mantle,accel_crust_mantle, &
-                    displ_inner_core,veloc_inner_core,accel_inner_core, &
-                    displ_outer_core,veloc_outer_core,accel_outer_core, &
-                    R_memory_crust_mantle,R_memory_inner_core, &
-                    epsilondev_crust_mantle,epsilondev_inner_core, &
-                    A_array_rotation,B_array_rotation, &
-                    LOCAL_PATH)
-
-  ! synchronize all processes
-  call MPI_BARRIER(MPI_COMM_WORLD,ier)
-  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize saving forward')
-
-  ! dump kernel arrays
-  if (SIMULATION_TYPE == 3) then
-    ! crust mantle
-    call save_kernels_crust_mantle(myrank,scale_t,scale_displ, &
-                  cijkl_kl_crust_mantle,rho_kl_crust_mantle, &
-                  alpha_kl_crust_mantle,beta_kl_crust_mantle, &
-                  ystore_crust_mantle,zstore_crust_mantle, &
-                  rhostore_crust_mantle,muvstore_crust_mantle, &
-                  kappavstore_crust_mantle,ibool_crust_mantle, &
-                  kappahstore_crust_mantle,muhstore_crust_mantle, &
-                  eta_anisostore_crust_mantle,ispec_is_tiso_crust_mantle, &
-              ! --idoubling_crust_mantle, &
-                  LOCAL_PATH)
-
-!<YANGL
-    ! noise strength kernel
-    if (NOISE_TOMOGRAPHY == 3) then
-       call save_kernels_strength_noise(myrank,LOCAL_PATH,Sigma_kl_crust_mantle)
-    endif
-!>YANGL
-
-    ! outer core
-    call save_kernels_outer_core(myrank,scale_t,scale_displ, &
-                        rho_kl_outer_core,alpha_kl_outer_core, &
-                        rhostore_outer_core,kappavstore_outer_core, &
-                        deviatoric_outercore,nspec_beta_kl_outer_core,beta_kl_outer_core, &
-                        LOCAL_PATH)
-
-    ! inner core
-    call save_kernels_inner_core(myrank,scale_t,scale_displ, &
-                          rho_kl_inner_core,beta_kl_inner_core,alpha_kl_inner_core, &
-                          rhostore_inner_core,muvstore_inner_core,kappavstore_inner_core, &
-                          LOCAL_PATH)
-
-    ! boundary kernel
-    if (SAVE_BOUNDARY_MESH) then
-      call save_kernels_boundary_kl(myrank,scale_t,scale_displ, &
-                                  moho_kl,d400_kl,d670_kl,cmb_kl,icb_kl, &
-                                  LOCAL_PATH,HONOR_1D_SPHERICAL_MOHO)
-    endif
-
-    ! approximate hessian
-    if( APPROXIMATE_HESS_KL ) then
-      call save_kernels_hessian(myrank,scale_t,scale_displ, &
-                                            hess_kl_crust_mantle,LOCAL_PATH)
-    endif
-  endif
-
-  ! save source derivatives for adjoint simulations
-  if (SIMULATION_TYPE == 2 .and. nrec_local > 0) then
-    call save_kernels_source_derivatives(nrec_local,NSOURCES,scale_displ,scale_t, &
-                                nu_source,moment_der,sloc_der,stshift_der,shdur_der,number_receiver_global)
-  endif
-
-  ! close the main output file
-  if(myrank == 0) then
-    write(IMAIN,*)
-    write(IMAIN,*) 'End of the simulation'
-    write(IMAIN,*)
-    close(IMAIN)
-  endif
-
-  ! synchronize all the processes to make sure everybody has finished
-  call MPI_BARRIER(MPI_COMM_WORLD,ier)
-  if( ier /= 0 ) call exit_mpi(myrank,'error synchronize finishing simulation')
-
-  ! stop all the MPI processes, and exit
-  call MPI_FINALIZE(ier)
-
-  end program xspecfem3D
-

Modified: seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/write_movie_volume.f90
===================================================================
--- seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/write_movie_volume.f90	2011-09-28 00:00:36 UTC (rev 18977)
+++ seismo/3D/SPECFEM3D_GLOBE/trunk/src/specfem3D/write_movie_volume.f90	2011-09-28 00:05:15 UTC (rev 18978)
@@ -150,106 +150,107 @@
     NIT = 1
   endif
 
-   ipoints_3dmovie=0
-    do ispec=1,NSPEC_CRUST_MANTLE
-     do k=1,NGLLZ,NIT
+  ipoints_3dmovie=0
+  do ispec=1,NSPEC_CRUST_MANTLE
+    do k=1,NGLLZ,NIT
       do j=1,NGLLY,NIT
-       do i=1,NGLLX,NIT
-         if(mask_3dmovie(i,j,k,ispec)) then
-          ipoints_3dmovie=ipoints_3dmovie+1
-          iglob= ibool_crust_mantle(i,j,k,ispec)
-          rval     = xstore_crust_mantle(iglob)
-          thetaval = ystore_crust_mantle(iglob)
-          phival   = zstore_crust_mantle(iglob)
-!x,y,z store have been converted to r theta phi already, need to revert back for xyz output
-          call rthetaphi_2_xyz(xval,yval,zval,rval,thetaval,phival)
-          store_val3D_x(ipoints_3dmovie)=xval
-          store_val3D_y(ipoints_3dmovie)=yval
-          store_val3D_z(ipoints_3dmovie)=zval
-          store_val3D_mu(ipoints_3dmovie)=muvstore_crust_mantle_3dmovie(i,j,k,ispec)
-          st = sin(thetaval)
-          ct = cos(thetaval)
-          sp = sin(phival)
-          cp = cos(phival)
-          nu_3dmovie(1,1,ipoints_3dmovie)=-ct*cp
-          nu_3dmovie(1,2,ipoints_3dmovie)=-ct*sp
-          nu_3dmovie(1,3,ipoints_3dmovie)=st
-          nu_3dmovie(2,1,ipoints_3dmovie)=-sp
-          nu_3dmovie(2,2,ipoints_3dmovie)=cp
-          nu_3dmovie(2,3,ipoints_3dmovie)=0.d0
-          nu_3dmovie(3,1,ipoints_3dmovie)=st*cp
-          nu_3dmovie(3,2,ipoints_3dmovie)=st*sp
-          nu_3dmovie(3,3,ipoints_3dmovie)=ct
-        endif !mask_3dmovie
-       enddo  !i
+        do i=1,NGLLX,NIT
+          if(mask_3dmovie(i,j,k,ispec)) then
+            ipoints_3dmovie=ipoints_3dmovie+1
+            iglob= ibool_crust_mantle(i,j,k,ispec)
+            rval     = xstore_crust_mantle(iglob)
+            thetaval = ystore_crust_mantle(iglob)
+            phival   = zstore_crust_mantle(iglob)
+            !x,y,z store have been converted to r theta phi already, need to revert back for xyz output
+            call rthetaphi_2_xyz(xval,yval,zval,rval,thetaval,phival)
+            store_val3D_x(ipoints_3dmovie)=xval
+            store_val3D_y(ipoints_3dmovie)=yval
+            store_val3D_z(ipoints_3dmovie)=zval
+            store_val3D_mu(ipoints_3dmovie)=muvstore_crust_mantle_3dmovie(i,j,k,ispec)
+            st = sin(thetaval)
+            ct = cos(thetaval)
+            sp = sin(phival)
+            cp = cos(phival)
+            nu_3dmovie(1,1,ipoints_3dmovie)=-ct*cp
+            nu_3dmovie(1,2,ipoints_3dmovie)=-ct*sp
+            nu_3dmovie(1,3,ipoints_3dmovie)=st
+            nu_3dmovie(2,1,ipoints_3dmovie)=-sp
+            nu_3dmovie(2,2,ipoints_3dmovie)=cp
+            nu_3dmovie(2,3,ipoints_3dmovie)=0.d0
+            nu_3dmovie(3,1,ipoints_3dmovie)=st*cp
+            nu_3dmovie(3,2,ipoints_3dmovie)=st*sp
+            nu_3dmovie(3,3,ipoints_3dmovie)=ct
+          endif !mask_3dmovie
+        enddo  !i
       enddo  !j
-     enddo  !k
-    enddo !ispec
-   open(unit=IOUT,file=trim(prname)//'movie3D_x.bin',status='unknown',form='unformatted')
-   if(npoints_3dmovie>0) then
-     write(IOUT) store_val3D_x(1:npoints_3dmovie)
+    enddo  !k
+  enddo !ispec
+  open(unit=IOUT,file=trim(prname)//'movie3D_x.bin',status='unknown',form='unformatted')
+  if(npoints_3dmovie>0) then
+    write(IOUT) store_val3D_x(1:npoints_3dmovie)
+  endif
+  close(IOUT)
+  open(unit=IOUT,file=trim(prname)//'movie3D_y.bin',status='unknown',form='unformatted')
+  if(npoints_3dmovie>0) then
+    write(IOUT) store_val3D_y(1:npoints_3dmovie)
    endif
-   close(IOUT)
-   open(unit=IOUT,file=trim(prname)//'movie3D_y.bin',status='unknown',form='unformatted')
-   if(npoints_3dmovie>0) then
-     write(IOUT) store_val3D_y(1:npoints_3dmovie)
-   endif
-   close(IOUT)
+  close(IOUT)
 
-   open(unit=IOUT,file=trim(prname)//'movie3D_z.bin',status='unknown',form='unformatted')
-   if(npoints_3dmovie>0) then
-     write(IOUT) store_val3D_z(1:npoints_3dmovie)
-   endif
-   close(IOUT)
+  open(unit=IOUT,file=trim(prname)//'movie3D_z.bin',status='unknown',form='unformatted')
+  if(npoints_3dmovie>0) then
+    write(IOUT) store_val3D_z(1:npoints_3dmovie)
+  endif
+  close(IOUT)
 
-   open(unit=IOUT,file=trim(prname)//'ascii_output.txt',status='unknown')
-   if(npoints_3dmovie>0) then
-     do i=1,npoints_3dmovie
-       write(IOUT,*) store_val3D_x(i),store_val3D_y(i),store_val3D_z(i),store_val3D_mu(i)
-     enddo
-   endif
-   close(IOUT)
-   open(unit=IOUT,file=trim(prname)//'movie3D_elements.bin',status='unknown',form='unformatted')
-   ispecele=0
+  open(unit=IOUT,file=trim(prname)//'ascii_output.txt',status='unknown')
+  if(npoints_3dmovie>0) then
+    do i=1,npoints_3dmovie
+      write(IOUT,*) store_val3D_x(i),store_val3D_y(i),store_val3D_z(i),store_val3D_mu(i)
+    enddo
+  endif
+  close(IOUT)
+  open(unit=IOUT,file=trim(prname)//'movie3D_elements.bin',status='unknown',form='unformatted')
+  ispecele=0
  !  open(unit=IOUT,file=trim(prname)//'movie3D_elements.txt',status='unknown')
-   do ispec=1,NSPEC_CRUST_MANTLE
+  do ispec=1,NSPEC_CRUST_MANTLE
     if(MOVIE_COARSE) then
       iglob=ibool_crust_mantle(1,1,1,ispec)
     else
       iglob=ibool_crust_mantle(3,3,3,ispec)
     endif
     if(mask_ibool_3dmovie(iglob)) then  !this element is in the region
-     ispecele  = ispecele+1
-     do k=1,NGLLZ-1,NIT
-      do j=1,NGLLY-1,NIT
-       do i=1,NGLLX-1,NIT
-        ! if(mask_3dmovie(i,j,k,ispec)) then
-          iglob1 = ibool_crust_mantle(i,j,k,ispec)
-          iglob2 = ibool_crust_mantle(i+NIT,j,k,ispec)
-          iglob3 = ibool_crust_mantle(i+NIT,j+NIT,k,ispec)
-          iglob4 = ibool_crust_mantle(i,j+NIT,k,ispec)
-          iglob5 = ibool_crust_mantle(i,j,k+NIT,ispec)
-          iglob6 = ibool_crust_mantle(i+NIT,j,k+NIT,ispec)
-          iglob7 = ibool_crust_mantle(i+NIT,j+NIT,k+NIT,ispec)
-          iglob8 = ibool_crust_mantle(i,j+NIT,k+NIT,ispec)
-          n1 = num_ibool_3dmovie(iglob1)-1
-          n2 = num_ibool_3dmovie(iglob2)-1
-          n3 = num_ibool_3dmovie(iglob3)-1
-          n4 = num_ibool_3dmovie(iglob4)-1
-          n5 = num_ibool_3dmovie(iglob5)-1
-          n6 = num_ibool_3dmovie(iglob6)-1
-          n7 = num_ibool_3dmovie(iglob7)-1
-          n8 = num_ibool_3dmovie(iglob8)-1
-          write(IOUT) n1,n2,n3,n4,n5,n6,n7,n8
-        !  write(57,*) n1,n2,n3,n4,n5,n6,n7,n8
-       !  endif !mask3dmovie
-       enddo !i
-      enddo !j
-     enddo !k
+      ispecele  = ispecele+1
+      do k=1,NGLLZ-1,NIT
+        do j=1,NGLLY-1,NIT
+          do i=1,NGLLX-1,NIT
+            ! if(mask_3dmovie(i,j,k,ispec)) then
+            iglob1 = ibool_crust_mantle(i,j,k,ispec)
+            iglob2 = ibool_crust_mantle(i+NIT,j,k,ispec)
+            iglob3 = ibool_crust_mantle(i+NIT,j+NIT,k,ispec)
+            iglob4 = ibool_crust_mantle(i,j+NIT,k,ispec)
+            iglob5 = ibool_crust_mantle(i,j,k+NIT,ispec)
+            iglob6 = ibool_crust_mantle(i+NIT,j,k+NIT,ispec)
+            iglob7 = ibool_crust_mantle(i+NIT,j+NIT,k+NIT,ispec)
+            iglob8 = ibool_crust_mantle(i,j+NIT,k+NIT,ispec)
+            n1 = num_ibool_3dmovie(iglob1)-1
+            n2 = num_ibool_3dmovie(iglob2)-1
+            n3 = num_ibool_3dmovie(iglob3)-1
+            n4 = num_ibool_3dmovie(iglob4)-1
+            n5 = num_ibool_3dmovie(iglob5)-1
+            n6 = num_ibool_3dmovie(iglob6)-1
+            n7 = num_ibool_3dmovie(iglob7)-1
+            n8 = num_ibool_3dmovie(iglob8)-1
+            write(IOUT) n1,n2,n3,n4,n5,n6,n7,n8
+            !  write(57,*) n1,n2,n3,n4,n5,n6,n7,n8
+            !  endif !mask3dmovie
+          enddo !i
+        enddo !j
+      enddo !k
     endif
-    enddo !ispec
+  enddo !ispec
   close(IOUT)
 !  close(57)
+
  end subroutine write_movie_volume_mesh
 
 ! ---------------------------------------------
@@ -377,7 +378,8 @@
 
 ! ---------------------------------------------
   subroutine write_movie_volume_vector(myrank,it,npoints_3dmovie,LOCAL_PATH,MOVIE_VOLUME_TYPE, &
-                    MOVIE_COARSE,ibool_crust_mantle,vector_crust_mantle,scalingval,mask_3dmovie,nu_3dmovie)
+                                      MOVIE_COARSE,ibool_crust_mantle,vector_crust_mantle, &
+                                      scalingval,mask_3dmovie,nu_3dmovie)
   implicit none
 
   include "constants.h"
@@ -467,77 +469,716 @@
 !--------------------
 
  subroutine write_movie_volume_divcurl(myrank,it,eps_trace_over_3_crust_mantle,&
-          accel_outer_core,kappavstore_outer_core,rhostore_outer_core,ibool_outer_core, &
-          eps_trace_over_3_inner_core,epsilondev_crust_mantle,&
-          epsilondev_inner_core)
-    include "constants.h"
-    include "OUTPUT_FILES/values_from_mesher.h"
-    ! div
-    integer :: myrank,it,ispec,iglob,i,j,k
-    real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STR_OR_ATT) :: epsilondev_inner_core
-    real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STRAIN_ONLY) :: eps_trace_over_3_inner_core
-    real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: rhostore_outer_core, &
-                            kappavstore_outer_core,ibool_outer_core
-    real(kind=CUSTOM_REAL), dimension(NGLOB_CRUST_MANTLE) :: accel_outer_core
-    real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: eps_trace_over_3_crust_mantle
-    real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilondev_crust_mantle
-    real(kind=CUSTOM_REAL) :: rhol,kappal
-    real(kind=CUSTOM_REAL), dimension(:,:,:,:), allocatable :: div_s_outer_core
+                        div_displ_outer_core, &
+                        accel_outer_core,kappavstore_outer_core,rhostore_outer_core,ibool_outer_core, &
+                        eps_trace_over_3_inner_core, &
+                        epsilondev_crust_mantle,epsilondev_inner_core, &
+                        LOCAL_PATH, &
+                        displ_crust_mantle,displ_inner_core,displ_outer_core, &
+                        veloc_crust_mantle,veloc_inner_core,veloc_outer_core, &
+                        accel_crust_mantle,accel_inner_core, &
+                        ibool_crust_mantle,ibool_inner_core)
+  
+  implicit none
+  include "constants.h"
+  include "OUTPUT_FILES/values_from_mesher.h"
+  
+  integer :: myrank,it
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: eps_trace_over_3_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT) :: div_displ_outer_core
 
-    character(len=150) LOCAL_PATH,outputname
+  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: accel_outer_core
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: &
+        rhostore_outer_core,kappavstore_outer_core
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE) :: ibool_outer_core
 
+  real(kind=CUSTOM_REAL), dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STRAIN_ONLY) :: eps_trace_over_3_inner_core  
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: epsilondev_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(5,NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE_STR_OR_ATT) :: epsilondev_inner_core
 
-    write(outputname,"('proc',i6.6,'_crust_mantle_div_displ_it',i6.6,'.bin')") myrank,it
-    open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
+  character(len=150) LOCAL_PATH
+
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: displ_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: veloc_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_CRUST_MANTLE) :: accel_crust_mantle
+  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: veloc_outer_core
+  real(kind=CUSTOM_REAL), dimension(NGLOB_OUTER_CORE) :: displ_outer_core
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: displ_inner_core
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: veloc_inner_core
+  real(kind=CUSTOM_REAL), dimension(NDIM,NGLOB_INNER_CORE) :: accel_inner_core
+
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE) :: ibool_crust_mantle
+  integer, dimension(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE) :: ibool_inner_core
+
+  ! local parameters
+  real(kind=CUSTOM_REAL) :: rhol,kappal
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:), allocatable :: div_s_outer_core
+  integer :: ispec,iglob,i,j,k,ier
+  character(len=150) outputname
+  real(kind=CUSTOM_REAL), dimension(:,:,:,:), allocatable :: tmp_data
+  real(kind=CUSTOM_REAL) :: scale_displ,scale_veloc,scale_accel
+  
+  ! output parameters
+  logical,parameter :: MOVIE_OUTPUT_DIV = .true.          ! divergence
+  logical,parameter :: MOVIE_OUTPUT_CURL = .false.        ! curl 
+  logical,parameter :: MOVIE_OUTPUT_CURLNORM = .true.     ! frobenius norm of curl
+  logical,parameter :: MOVIE_OUTPUT_DISPLNORM = .false.   ! norm of displacement
+  logical,parameter :: MOVIE_OUTPUT_VELOCNORM = .false.   ! norm of velocity
+  logical,parameter :: MOVIE_OUTPUT_ACCELNORM = .false.   ! norm of acceleration
+
+  ! outputs divergence
+  if( MOVIE_OUTPUT_DIV ) then  
+    ! crust_mantle region
+    ! these binary arrays can be converted into mesh format using the utilitiy ./bin/xcombine_vol_data
+    ! old name format:     write(outputname,"('proc',i6.6,'_crust_mantle_div_displ_it',i6.6,'.bin')") myrank,it
+    write(outputname,"('proc',i6.6,'_reg1_div_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))  
     write(27) eps_trace_over_3_crust_mantle
     close(27)
+    
+    ! outer core
+    if (NSPEC_OUTER_CORE_ADJOINT /= 1 ) then
+      write(outputname,"('proc',i6.6,'_reg2_div_displ_it',i6.6,'.bin')") myrank,it
+      open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+      if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+      write(27)  ONE_THIRD * div_displ_outer_core
+      close(27)
+    else
+      ! we use div s = - p / kappa = rhostore_outer_core * accel_outer_core / kappavstore_outer_core
+      allocate(div_s_outer_core(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE))
+      do ispec = 1, NSPEC_OUTER_CORE
+        do k = 1, NGLLZ
+          do j = 1, NGLLY
+            do i = 1, NGLLX
+              iglob = ibool_outer_core(i,j,k,ispec)
+              rhol = rhostore_outer_core(i,j,k,ispec)
+              kappal = kappavstore_outer_core(i,j,k,ispec)
+              div_s_outer_core(i,j,k,ispec) = rhol * accel_outer_core(iglob) / kappal
+            enddo
+          enddo
+        enddo
+      enddo
+      
+      ! old name format: write(outputname,"('proc',i6.6,'_outer_core_div_displ_it',i6.6,'.bin')") myrank,it
+      write(outputname,"('proc',i6.6,'_reg2_div_displ_it',i6.6,'.bin')") myrank,it
+      open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+      if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+      write(27)  div_s_outer_core
+      close(27)
 
-! we use div s = - p / kappa = rhostore_outer_core * accel_outer_core / kappavstore_outer_core
-    allocate(div_s_outer_core(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE_ADJOINT))
+      deallocate(div_s_outer_core)
+    endif
+    
+    ! inner core
+    ! old name format: write(outputname,"('proc',i6.6,'_inner_core_div_displ_proc_it',i6.6,'.bin')") myrank,it
+    write(outputname,"('proc',i6.6,'_reg3_div_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) eps_trace_over_3_inner_core
+    close(27)
+
+  endif
+
+  ! outputs epsilondev
+  if( MOVIE_OUTPUT_CURL ) then
+    ! epsilondev
+    ! these binary files must be handled by the user, no further utilities available for this format
+    ! crust mantle
+    write(outputname,"('proc',i6.6,'_crust_mantle_epsdev_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
+    write(27) epsilondev_crust_mantle
+    close(27)
+    ! inner core
+    write(outputname,"('proc',i6.6,'inner_core_epsdev_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
+    write(27) epsilondev_inner_core
+    close(27)
+  endif
+  
+  ! outputs norm of epsilondev
+  if( MOVIE_OUTPUT_CURLNORM ) then
+    ! these binary arrays can be converted into mesh format using the utilitiy ./bin/xcombine_vol_data    
+    ! crust_mantle region
+    write(outputname,"('proc',i6.6,'_reg1_epsdev_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    ! frobenius norm
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE))
+    do ispec = 1, NSPEC_CRUST_MANTLE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX    
+            tmp_data(i,j,k,ispec) = sqrt( epsilondev_crust_mantle(1,i,j,k,ispec)**2 &
+                                          + epsilondev_crust_mantle(2,i,j,k,ispec)**2 &
+                                          + epsilondev_crust_mantle(3,i,j,k,ispec)**2 &
+                                          + epsilondev_crust_mantle(4,i,j,k,ispec)**2 &
+                                          + epsilondev_crust_mantle(5,i,j,k,ispec)**2)                                          
+          enddo
+        enddo
+      enddo
+    enddo
+    write(27) tmp_data
+    close(27)
+    deallocate(tmp_data)
+    
+    ! alternative: e.g. first component only
+    !write(27) epsilondev_crust_mantle(1,:,:,:,:)
+    !close(27)
+
+    ! inner core
+    write(outputname,"('proc',i6.6,'_reg3_epsdev_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    ! frobenius norm
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE))
+    do ispec = 1, NSPEC_INNER_CORE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX    
+            tmp_data(i,j,k,ispec) = sqrt( epsilondev_inner_core(1,i,j,k,ispec)**2 &
+                                          + epsilondev_inner_core(2,i,j,k,ispec)**2 &
+                                          + epsilondev_inner_core(3,i,j,k,ispec)**2 &
+                                          + epsilondev_inner_core(4,i,j,k,ispec)**2 &
+                                          + epsilondev_inner_core(5,i,j,k,ispec)**2)                                          
+          enddo
+        enddo
+      enddo
+    enddo
+    write(27) tmp_data
+    close(27)
+    deallocate(tmp_data)
+
+    ! alternative: e.g. first component only
+    !write(27) epsilondev_inner_core(1,:,:,:,:)
+    !close(27)
+  endif
+
+  ! dimensionalized scalings
+  scale_displ = R_EARTH
+  scale_veloc = scale_displ * sqrt(PI*GRAV*RHOAV)
+  scale_accel = scale_veloc * dsqrt(PI*GRAV*RHOAV)
+    
+  ! outputs norm of displacement 
+  if( MOVIE_OUTPUT_DISPLNORM ) then
+    ! crust mantle
+    ! these binary arrays can be converted into mesh format using the utilitiy ./bin/xcombine_vol_data        
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE))
+    do ispec = 1, NSPEC_CRUST_MANTLE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_crust_mantle(i,j,k,ispec)
+            ! norm
+            tmp_data(i,j,k,ispec) = scale_displ * sqrt( displ_crust_mantle(1,iglob)**2 &
+                                          + displ_crust_mantle(2,iglob)**2 &
+                                          + displ_crust_mantle(3,iglob)**2 )
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg1_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
+    close(27)
+    deallocate(tmp_data)
+
+    ! outer core
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE))
     do ispec = 1, NSPEC_OUTER_CORE
       do k = 1, NGLLZ
         do j = 1, NGLLY
           do i = 1, NGLLX
             iglob = ibool_outer_core(i,j,k,ispec)
-            rhol = rhostore_outer_core(i,j,k,ispec)
-            kappal = kappavstore_outer_core(i,j,k,ispec)
-            div_s_outer_core(i,j,k,ispec) = rhol * accel_outer_core(iglob) / kappal
+            ! norm 
+            ! note: disp_outer_core is potential, this just outputs the potential, 
+            !          not the actual displacement u = grad(rho * Chi) / rho
+            tmp_data(i,j,k,ispec) = abs(displ_outer_core(iglob))
           enddo
         enddo
       enddo
     enddo
+    write(outputname,"('proc',i6.6,'_reg2_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
+    close(27)
+    deallocate(tmp_data)
 
-    write(outputname,"('proc',i6.6,'_outer_core_div_displ_it',i6.6,'.bin')") myrank,it
-    open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
-    write(27)  div_s_outer_core
+    ! inner core
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE))
+    do ispec = 1, NSPEC_INNER_CORE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_inner_core(i,j,k,ispec)
+            ! norm 
+            tmp_data(i,j,k,ispec) = scale_displ * sqrt( displ_inner_core(1,iglob)**2 &
+                                          + displ_inner_core(2,iglob)**2 &
+                                          + displ_inner_core(3,iglob)**2 )
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg3_displ_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
     close(27)
+    deallocate(tmp_data)
+  endif
 
-    deallocate(div_s_outer_core)
 
+  ! outputs norm of velocity 
+  if( MOVIE_OUTPUT_VELOCNORM ) then
+    ! crust mantle
+    ! these binary arrays can be converted into mesh format using the utilitiy ./bin/xcombine_vol_data        
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE))
+    do ispec = 1, NSPEC_CRUST_MANTLE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_crust_mantle(i,j,k,ispec)
+            ! norm of velocity
+            tmp_data(i,j,k,ispec) = scale_veloc * sqrt( veloc_crust_mantle(1,iglob)**2 &
+                                          + veloc_crust_mantle(2,iglob)**2 &
+                                          + veloc_crust_mantle(3,iglob)**2 )
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg1_veloc_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
+    close(27)
+    deallocate(tmp_data)
 
-  !  write(outputname,"('proc',i6.6,'_outer_core_div_displ_it',i6.6,'.bin')") myrank,it
-  !  open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
-  !  write(27)  ONE_THIRD * div_displ_outer_core
-  !  close(27)
+    ! outer core
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE))
+    do ispec = 1, NSPEC_OUTER_CORE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_outer_core(i,j,k,ispec)
+            ! norm of velocity
+            ! note: this outputs only the first time derivative of the potential,
+            !          not the actual velocity v = grad(Chi_dot)
+            tmp_data(i,j,k,ispec) = abs(veloc_outer_core(iglob))
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg2_veloc_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
+    close(27)
+    deallocate(tmp_data)
 
-    write(outputname,"('proc',i6.6,'_inner_core_div_displ_proc_it',i6.6,'.bin')") myrank,it
-    open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
-    write(27) eps_trace_over_3_inner_core
+    ! inner core
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE))
+    do ispec = 1, NSPEC_INNER_CORE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_inner_core(i,j,k,ispec)
+            ! norm of velocity
+            tmp_data(i,j,k,ispec) = scale_veloc * sqrt( veloc_inner_core(1,iglob)**2 &
+                                          + veloc_inner_core(2,iglob)**2 &
+                                          + veloc_inner_core(3,iglob)**2 )
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg3_veloc_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
     close(27)
+    deallocate(tmp_data)
+  endif
+  
+  ! outputs norm of acceleration
+  if( MOVIE_OUTPUT_ACCELNORM ) then    
+    ! acceleration
+    ! these binary arrays can be converted into mesh format using the utilitiy ./bin/xcombine_vol_data        
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_CRUST_MANTLE))
+    do ispec = 1, NSPEC_CRUST_MANTLE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_crust_mantle(i,j,k,ispec)
+            ! norm 
+            tmp_data(i,j,k,ispec) = scale_accel * sqrt( accel_crust_mantle(1,iglob)**2 &
+                                          + accel_crust_mantle(2,iglob)**2 &
+                                          + accel_crust_mantle(3,iglob)**2 )
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg1_accel_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
+    close(27)
+    deallocate(tmp_data)
 
-! epsilondev
-
-    write(outputname,"('proc',i6.6,'_crust_mantle_epsdev_displ_it',i6.6,'.bin')") myrank,it
-    open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
-    write(27) epsilondev_crust_mantle
+    ! outer core acceleration
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_OUTER_CORE))
+    do ispec = 1, NSPEC_OUTER_CORE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_outer_core(i,j,k,ispec)
+            ! norm 
+            ! note: this outputs only the second time derivative of the potential,
+            !          not the actual acceleration or pressure p = - rho * Chi_dot_dot 
+            tmp_data(i,j,k,ispec) = abs(accel_outer_core(iglob))
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg2_accel_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
     close(27)
+    deallocate(tmp_data)
 
-    write(outputname,"('proc',i6.6,'inner_core_epsdev_displ_it',i6.6,'.bin')") myrank,it
-    open(unit=27,file=trim(LOCAL_PATH)//trim(outputname),status='unknown',form='unformatted')
-    write(27) epsilondev_inner_core
+    ! inner core
+    allocate(tmp_data(NGLLX,NGLLY,NGLLZ,NSPEC_INNER_CORE))
+    do ispec = 1, NSPEC_INNER_CORE
+      do k = 1, NGLLZ
+        do j = 1, NGLLY
+          do i = 1, NGLLX
+            iglob = ibool_inner_core(i,j,k,ispec)
+            ! norm of velocity
+            tmp_data(i,j,k,ispec) = scale_accel * sqrt( accel_inner_core(1,iglob)**2 &
+                                          + accel_inner_core(2,iglob)**2 &
+                                          + accel_inner_core(3,iglob)**2 )
+          enddo
+        enddo
+      enddo
+    enddo
+    write(outputname,"('proc',i6.6,'_reg3_accel_it',i6.6,'.bin')") myrank,it
+    open(unit=27,file=trim(LOCAL_PATH)//'/'//trim(outputname),status='unknown',form='unformatted',iostat=ier)
+    if( ier /= 0 ) call exit_MPI(myrank,'error opening file '//trim(outputname))
+    write(27) tmp_data
     close(27)
+    deallocate(tmp_data)
+  endif
 
-
   end subroutine write_movie_volume_divcurl
 
 
+!-------------------------------------------------------------------------------------------------
+
+! external mesh routine for saving vtk files for custom_real values on global points
+
+  subroutine write_VTK_data_cr(idoubling,nspec,nglob, &
+                              xstore_dummy,ystore_dummy,zstore_dummy,ibool, &
+                              glob_data,prname_file)
+
+! outputs single file for each process
+
+  implicit none
+
+  include "constants.h"
+
+  integer :: nspec,nglob
+
+  integer, dimension(nspec):: idoubling
+
+  ! global coordinates
+  integer, dimension(NGLLX,NGLLY,NGLLZ,nspec) :: ibool
+  real(kind=CUSTOM_REAL), dimension(nglob) :: xstore_dummy,ystore_dummy,zstore_dummy
+
+  ! global data values array
+  real(kind=CUSTOM_REAL), dimension(NDIM,nglob) :: glob_data
+
+  ! file name
+  character(len=256) prname_file
+
+  ! local parameters
+  integer :: ispec,i
+  real(kind=CUSTOM_REAL) :: rval,thetaval,phival,xval,yval,zval
+
+  ! write source and receiver VTK files for Paraview
+  open(IOVTK,file=prname_file(1:len_trim(prname_file))//'.vtk',status='unknown')
+  write(IOVTK,'(a)') '# vtk DataFile Version 3.1'
+  write(IOVTK,'(a)') 'material model VTK file'
+  write(IOVTK,'(a)') 'ASCII'
+  write(IOVTK,'(a)') 'DATASET UNSTRUCTURED_GRID'
+  write(IOVTK, '(a,i12,a)') 'POINTS ', nglob, ' float'
+  do i=1,nglob
+
+    !x,y,z store have been converted to r theta phi already, need to revert back for xyz output
+    rval = xstore_dummy(i)
+    thetaval = ystore_dummy(i)
+    phival = zstore_dummy(i)
+    call rthetaphi_2_xyz(xval,yval,zval,rval,thetaval,phival)
+
+    !write(IOVTK,'(3e18.6)') xstore_dummy(i),ystore_dummy(i),zstore_dummy(i)
+    write(IOVTK,'(3e18.6)') xval,yval,zval
+  enddo
+  write(IOVTK,*) ""
+
+  ! defines cell on coarse corner points
+  ! note: indices for vtk start at 0
+  write(IOVTK,'(a,i12,i12)') "CELLS ",nspec,nspec*9
+  do ispec=1,nspec
+
+    ! specific to inner core elements
+    ! exclude fictitious elements in central cube
+    if(idoubling(ispec) /= IFLAG_IN_FICTITIOUS_CUBE) then
+      ! valid cell
+      write(IOVTK,'(9i12)') 8,ibool(1,1,1,ispec)-1, &
+                          ibool(NGLLX,1,1,ispec)-1, &
+                          ibool(NGLLX,NGLLY,1,ispec)-1, &
+                          ibool(1,NGLLY,1,ispec)-1, &
+                          ibool(1,1,NGLLZ,ispec)-1, &
+                          ibool(NGLLX,1,NGLLZ,ispec)-1, &
+                          ibool(NGLLX,NGLLY,NGLLZ,ispec)-1, &
+                          ibool(1,NGLLY,NGLLZ,ispec)-1
+    else
+      ! fictitious elements in central cube
+      ! maps cell onto a randomly chosen point
+      write(IOVTK,'(9i12)') 8,ibool(1,1,1,1)-1, &
+                            ibool(1,1,1,1)-1, &
+                            ibool(1,1,1,1)-1, &
+                            ibool(1,1,1,1)-1, &
+                            ibool(1,1,1,1)-1, &
+                            ibool(1,1,1,1)-1, &
+                            ibool(1,1,1,1)-1, &
+                            ibool(1,1,1,1)-1
+    endif
+
+  enddo
+  write(IOVTK,*) ""
+
+  ! type: hexahedrons
+  write(IOVTK,'(a,i12)') "CELL_TYPES ",nspec
+  write(IOVTK,*) (12,ispec=1,nspec)
+  write(IOVTK,*) ""
+
+  ! x components
+  write(IOVTK,'(a,i12)') "POINT_DATA ",nglob
+  write(IOVTK,'(a)') "SCALARS x_comp float"
+  write(IOVTK,'(a)') "LOOKUP_TABLE default"
+  do i = 1,nglob
+      write(IOVTK,*) glob_data(1,i)
+  enddo
+  ! y components
+  write(IOVTK,'(a)') "SCALARS y_comp float"
+  write(IOVTK,'(a)') "LOOKUP_TABLE default"
+  do i = 1,nglob
+      write(IOVTK,*) glob_data(2,i)
+  enddo
+  ! z components
+  write(IOVTK,'(a)') "SCALARS z_comp float"
+  write(IOVTK,'(a)') "LOOKUP_TABLE default"
+  do i = 1,nglob
+      write(IOVTK,*) glob_data(3,i)
+  enddo
+  ! norm
+  write(IOVTK,'(a)') "SCALARS norm float"
+  write(IOVTK,'(a)') "LOOKUP_TABLE default"
+  do i = 1,nglob
+      write(IOVTK,*) sqrt( glob_data(1,i)*glob_data(1,i) &
+                        + glob_data(2,i)*glob_data(2,i) &
+                        + glob_data(3,i)*glob_data(3,i))
+  enddo
+  write(IOVTK,*) ""
+
+  close(IOVTK)
+
+
+  end subroutine write_VTK_data_cr
+
+!-------------------------------------------------------------------------------------------------
+
+! external mesh routine for saving vtk files for custom_real values on global points
+
+  subroutine write_VTK_data_cr_all(myrank,idoubling, &
+                              nspec,nglob, &
+                              xstore_dummy,ystore_dummy,zstore_dummy,ibool, &
+                              glob_data,prname_file)
+
+! outputs single file for all processes
+
+  implicit none
+
+  include 'mpif.h'
+  include "precision.h"
+  include "constants.h"
+  include "OUTPUT_FILES/values_from_mesher.h"
+
+  integer :: myrank,nspec,nglob
+
+  integer, dimension(nspec):: idoubling
+
+  ! global coordinates
+  integer, dimension(NGLLX,NGLLY,NGLLZ,nspec) :: ibool
+  real(kind=CUSTOM_REAL), dimension(nglob) :: xstore_dummy,ystore_dummy,zstore_dummy
+
+  ! global data values array
+  real(kind=CUSTOM_REAL), dimension(NDIM,nglob) :: glob_data
+
+  ! file name
+  character(len=256) prname_file
+
+  ! local parameters
+  integer :: ispec,i,iproc,ier
+  real(kind=CUSTOM_REAL) :: rval,thetaval,phival,xval,yval,zval
+
+  real(kind=CUSTOM_REAL), dimension(:,:),allocatable :: &
+      store_val_x_all,store_val_y_all,store_val_z_all, &
+      store_val_ux_all,store_val_uy_all,store_val_uz_all
+  integer, dimension(:,:,:,:,:),allocatable :: ibool_all
+  integer, dimension(:,:),allocatable :: idoubling_all
+
+  ! master collect arrays
+  if( myrank == 0 ) then
+    allocate(store_val_x_all(nglob,0:NPROCTOT_VAL-1), &
+          store_val_y_all(nglob,0:NPROCTOT_VAL-1), &
+          store_val_z_all(nglob,0:NPROCTOT_VAL-1), &
+          store_val_ux_all(nglob,0:NPROCTOT_VAL-1), &
+          store_val_uy_all(nglob,0:NPROCTOT_VAL-1), &
+          store_val_uz_all(nglob,0:NPROCTOT_VAL-1), &
+          idoubling_all(nspec,0:NPROCTOT_VAL-1), &
+          ibool_all(NGLLX,NGLLY,NGLLZ,nspec,0:NPROCTOT_VAL-1),stat=ier)
+    if( ier /= 0 ) call exit_mpi(myrank,'error allocating stores')
+  endif
+
+  ! gather info on master proc
+  call MPI_GATHER(xstore_dummy,nglob,CUSTOM_MPI_TYPE,store_val_x_all,nglob,CUSTOM_MPI_TYPE,0,MPI_COMM_WORLD,ier)
+  call MPI_GATHER(ystore_dummy,nglob,CUSTOM_MPI_TYPE,store_val_y_all,nglob,CUSTOM_MPI_TYPE,0,MPI_COMM_WORLD,ier)
+  call MPI_GATHER(zstore_dummy,nglob,CUSTOM_MPI_TYPE,store_val_z_all,nglob,CUSTOM_MPI_TYPE,0,MPI_COMM_WORLD,ier)
+
+  call MPI_GATHER(glob_data(1,:),nglob,CUSTOM_MPI_TYPE,store_val_ux_all,nglob,CUSTOM_MPI_TYPE,0,MPI_COMM_WORLD,ier)
+  call MPI_GATHER(glob_data(2,:),nglob,CUSTOM_MPI_TYPE,store_val_uy_all,nglob,CUSTOM_MPI_TYPE,0,MPI_COMM_WORLD,ier)
+  call MPI_GATHER(glob_data(3,:),nglob,CUSTOM_MPI_TYPE,store_val_uz_all,nglob,CUSTOM_MPI_TYPE,0,MPI_COMM_WORLD,ier)
+
+  call MPI_GATHER(ibool,NGLLX*NGLLY*NGLLZ*nspec,MPI_INTEGER,ibool_all, &
+                  NGLLX*NGLLY*NGLLZ*nspec,MPI_INTEGER,0,MPI_COMM_WORLD,ier)
+  call MPI_GATHER(idoubling,nspec,MPI_INTEGER,idoubling_all,nspec,MPI_INTEGER,0,MPI_COMM_WORLD,ier)
+
+
+  if( myrank == 0 ) then
+
+    ! write source and receiver VTK files for Paraview
+    open(IOVTK,file=prname_file(1:len_trim(prname_file))//'.vtk',status='unknown')
+    write(IOVTK,'(a)') '# vtk DataFile Version 3.1'
+    write(IOVTK,'(a)') 'material model VTK file'
+    write(IOVTK,'(a)') 'ASCII'
+    write(IOVTK,'(a)') 'DATASET UNSTRUCTURED_GRID'
+    write(IOVTK, '(a,i12,a)') 'POINTS ', nglob*NPROCTOT_VAL, ' float'
+    do iproc=0, NPROCTOT_VAL-1
+      do i=1,nglob
+
+        !x,y,z store have been converted to r theta phi already, need to revert back for xyz output
+        rval = store_val_x_all(i,iproc)
+        thetaval = store_val_y_all(i,iproc)
+        phival = store_val_z_all(i,iproc)
+        call rthetaphi_2_xyz(xval,yval,zval,rval,thetaval,phival)
+
+        !write(IOVTK,'(3e18.6)') xstore_dummy(i),ystore_dummy(i),zstore_dummy(i)
+        write(IOVTK,'(3e18.6)') xval,yval,zval
+      enddo
+    enddo
+    write(IOVTK,*) ""
+
+    ! defines cell on coarse corner points
+    ! note: indices for vtk start at 0
+    write(IOVTK,'(a,i12,i12)') "CELLS ",nspec*NPROCTOT_VAL,nspec*NPROCTOT_VAL*9
+    do iproc=0, NPROCTOT_VAL-1
+      do ispec=1,nspec
+
+        ! note: central cube elements are only shared and used in CHUNK_AB and CHUNK_AB_ANTIPODE
+        !          all other chunks ignore those elements
+
+        ! specific to inner core elements
+        ! exclude fictitious elements in central cube
+        if(idoubling_all(ispec,iproc) /= IFLAG_IN_FICTITIOUS_CUBE) then
+          ! valid cell
+          ! cell corner ids
+          write(IOVTK,'(9i12)') 8,ibool_all(1,1,1,ispec,iproc)-1+iproc*nglob, &
+                            ibool_all(NGLLX,1,1,ispec,iproc)-1+iproc*nglob, &
+                            ibool_all(NGLLX,NGLLY,1,ispec,iproc)-1+iproc*nglob, &
+                            ibool_all(1,NGLLY,1,ispec,iproc)-1+iproc*nglob, &
+                            ibool_all(1,1,NGLLZ,ispec,iproc)-1+iproc*nglob, &
+                            ibool_all(NGLLX,1,NGLLZ,ispec,iproc)-1+iproc*nglob, &
+                            ibool_all(NGLLX,NGLLY,NGLLZ,ispec,iproc)-1+iproc*nglob, &
+                            ibool_all(1,NGLLY,NGLLZ,ispec,iproc)-1+iproc*nglob
+        else
+          ! fictitious elements in central cube
+          ! maps cell onto a randomly chosen point
+          write(IOVTK,'(9i12)') 8,ibool_all(1,1,1,1,iproc)-1, &
+                            ibool_all(1,1,1,1,iproc)-1, &
+                            ibool_all(1,1,1,1,iproc)-1, &
+                            ibool_all(1,1,1,1,iproc)-1, &
+                            ibool_all(1,1,1,1,iproc)-1, &
+                            ibool_all(1,1,1,1,iproc)-1, &
+                            ibool_all(1,1,1,1,iproc)-1, &
+                            ibool_all(1,1,1,1,iproc)-1
+        endif
+
+      enddo
+    enddo
+    write(IOVTK,*) ""
+
+    ! type: hexahedrons
+    write(IOVTK,'(a,i12)') "CELL_TYPES ",nspec*NPROCTOT_VAL
+    write(IOVTK,*) (12,ispec=1,nspec*NPROCTOT_VAL)
+    write(IOVTK,*) ""
+
+    ! x components
+    write(IOVTK,'(a,i12)') "POINT_DATA ",nglob*NPROCTOT_VAL
+    write(IOVTK,'(a)') "SCALARS x_comp float"
+    write(IOVTK,'(a)') "LOOKUP_TABLE default"
+    do iproc=0, NPROCTOT_VAL-1
+      do i = 1,nglob
+        write(IOVTK,*) store_val_ux_all(i,iproc)
+      enddo
+    enddo
+    ! y components
+    write(IOVTK,'(a)') "SCALARS y_comp float"
+    write(IOVTK,'(a)') "LOOKUP_TABLE default"
+    do iproc=0, NPROCTOT_VAL-1
+      do i = 1,nglob
+        write(IOVTK,*) store_val_uy_all(i,iproc)
+      enddo
+    enddo
+    ! z components
+    write(IOVTK,'(a)') "SCALARS z_comp float"
+    write(IOVTK,'(a)') "LOOKUP_TABLE default"
+    do iproc=0, NPROCTOT_VAL-1
+      do i = 1,nglob
+        write(IOVTK,*) store_val_uz_all(i,iproc)
+      enddo
+    enddo
+    ! norm
+    write(IOVTK,'(a)') "SCALARS norm float"
+    write(IOVTK,'(a)') "LOOKUP_TABLE default"
+    do iproc=0, NPROCTOT_VAL-1
+      do i = 1,nglob
+        write(IOVTK,*) sqrt( store_val_ux_all(i,iproc)**2 &
+                          + store_val_uy_all(i,iproc)**2 &
+                          + store_val_uz_all(i,iproc)**2 )
+      enddo
+    enddo
+    write(IOVTK,*) ""
+
+    close(IOVTK)
+
+  endif
+
+  if( myrank == 0 ) then
+    deallocate(store_val_x_all,store_val_y_all,store_val_z_all, &
+            store_val_ux_all,store_val_uy_all,store_val_uz_all, &
+            ibool_all)
+  endif
+
+  end subroutine write_VTK_data_cr_all



More information about the CIG-COMMITS mailing list