xref: /petsc/src/sys/ftn-custom/zutils.c (revision 95452b02e12c0ee11232c7ff2b24b568a8e07e43)
1af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
29306f9a3SSatish Balay 
30298fd71SBarry Smith void *PETSCNULLPOINTERADDRESS = NULL;
455fcb7f5SSatish Balay 
59306f9a3SSatish Balay /*MC
69306f9a3SSatish Balay    PetscFortranAddr - a variable type in Fortran that can hold a
79306f9a3SSatish Balay      regular C pointer.
89306f9a3SSatish Balay 
9*95452b02SPatrick Sanan    Notes:
10*95452b02SPatrick Sanan     Used, for example, as the file argument in PetscFOpen()
119306f9a3SSatish Balay 
129306f9a3SSatish Balay    Level: beginner
139306f9a3SSatish Balay 
149306f9a3SSatish Balay .seealso:  PetscOffset, PetscInt
159306f9a3SSatish Balay M*/
169306f9a3SSatish Balay /*MC
179306f9a3SSatish Balay    PetscOffset - a variable type in Fortran used with VecGetArray()
189306f9a3SSatish Balay      and ISGetIndices()
199306f9a3SSatish Balay 
209306f9a3SSatish Balay    Level: beginner
219306f9a3SSatish Balay 
229306f9a3SSatish Balay .seealso:  PetscFortranAddr, PetscInt
239306f9a3SSatish Balay M*/
249306f9a3SSatish Balay 
259306f9a3SSatish Balay /*
269306f9a3SSatish Balay     This is code for translating PETSc memory addresses to integer offsets
279306f9a3SSatish Balay     for Fortran.
289306f9a3SSatish Balay */
299306f9a3SSatish Balay char *PETSC_NULL_CHARACTER_Fortran = 0;
309306f9a3SSatish Balay void *PETSC_NULL_INTEGER_Fortran   = 0;
319306f9a3SSatish Balay void *PETSC_NULL_SCALAR_Fortran    = 0;
329306f9a3SSatish Balay void *PETSC_NULL_DOUBLE_Fortran    = 0;
339306f9a3SSatish Balay void *PETSC_NULL_REAL_Fortran      = 0;
345c550465SJed Brown void *PETSC_NULL_BOOL_Fortran      = 0;
359306f9a3SSatish Balay EXTERN_C_BEGIN
369306f9a3SSatish Balay void (*PETSC_NULL_FUNCTION_Fortran)(void) = 0;
379306f9a3SSatish Balay EXTERN_C_END
3899e0435eSBarry Smith 
398ea3bf28SBarry Smith size_t PetscIntAddressToFortran(const PetscInt *base,const PetscInt *addr)
409306f9a3SSatish Balay {
419306f9a3SSatish Balay   size_t tmp1 = (size_t) base,tmp2 = 0;
429306f9a3SSatish Balay   size_t tmp3 = (size_t) addr;
439306f9a3SSatish Balay   size_t itmp2;
449306f9a3SSatish Balay 
459306f9a3SSatish Balay #if !defined(PETSC_HAVE_CRAY90_POINTER)
469306f9a3SSatish Balay   if (tmp3 > tmp1) {
479306f9a3SSatish Balay     tmp2  = (tmp3 - tmp1)/sizeof(PetscInt);
489306f9a3SSatish Balay     itmp2 = (size_t) tmp2;
499306f9a3SSatish Balay   } else {
509306f9a3SSatish Balay     tmp2  = (tmp1 - tmp3)/sizeof(PetscInt);
519306f9a3SSatish Balay     itmp2 = -((size_t) tmp2);
529306f9a3SSatish Balay   }
539306f9a3SSatish Balay #else
549306f9a3SSatish Balay   if (tmp3 > tmp1) {
559306f9a3SSatish Balay     tmp2  = (tmp3 - tmp1);
569306f9a3SSatish Balay     itmp2 = (size_t) tmp2;
579306f9a3SSatish Balay   } else {
589306f9a3SSatish Balay     tmp2  = (tmp1 - tmp3);
599306f9a3SSatish Balay     itmp2 = -((size_t) tmp2);
609306f9a3SSatish Balay   }
619306f9a3SSatish Balay #endif
629306f9a3SSatish Balay 
639306f9a3SSatish Balay   if (base + itmp2 != addr) {
649306f9a3SSatish Balay     (*PetscErrorPrintf)("PetscIntAddressToFortran:C and Fortran arrays are\n");
659306f9a3SSatish Balay     (*PetscErrorPrintf)("not commonly aligned or are too far apart to be indexed \n");
669306f9a3SSatish Balay     (*PetscErrorPrintf)("by an integer. Locations: C %uld Fortran %uld\n",tmp1,tmp3);
679306f9a3SSatish Balay     MPI_Abort(PETSC_COMM_WORLD,1);
689306f9a3SSatish Balay   }
699306f9a3SSatish Balay   return itmp2;
709306f9a3SSatish Balay }
719306f9a3SSatish Balay 
728ea3bf28SBarry Smith PetscInt *PetscIntAddressFromFortran(const PetscInt *base,size_t addr)
739306f9a3SSatish Balay {
748ea3bf28SBarry Smith   return (PetscInt *)(base + addr);
759306f9a3SSatish Balay }
769306f9a3SSatish Balay 
779306f9a3SSatish Balay /*
789306f9a3SSatish Balay        obj - PETSc object on which request is made
799306f9a3SSatish Balay        base - Fortran array address
809306f9a3SSatish Balay        addr - C array address
819306f9a3SSatish Balay        res  - will contain offset from C to Fortran
829306f9a3SSatish Balay        shift - number of bytes that prevent base and addr from being commonly aligned
839306f9a3SSatish Balay        N - size of the array
849306f9a3SSatish Balay 
85f91d1997SBarry Smith        align indicates alignment relative to PetscScalar, 1 means aligned on PetscScalar, 2 means aligned on 2 PetscScalar etc
869306f9a3SSatish Balay */
87f91d1997SBarry Smith PetscErrorCode PetscScalarAddressToFortran(PetscObject obj,PetscInt align,PetscScalar *base,PetscScalar *addr,PetscInt N,size_t *res)
889306f9a3SSatish Balay {
89e366c363SBarry Smith   size_t   tmp1 = (size_t) base,tmp2;
909306f9a3SSatish Balay   size_t   tmp3 = (size_t) addr;
919306f9a3SSatish Balay   size_t   itmp2;
929306f9a3SSatish Balay   PetscInt shift;
939306f9a3SSatish Balay 
949306f9a3SSatish Balay #if !defined(PETSC_HAVE_CRAY90_POINTER)
959306f9a3SSatish Balay   if (tmp3 > tmp1) {  /* C is bigger than Fortran */
969306f9a3SSatish Balay     tmp2  = (tmp3 - tmp1)/sizeof(PetscScalar);
979306f9a3SSatish Balay     itmp2 = (size_t) tmp2;
98f91d1997SBarry Smith     shift = (align*sizeof(PetscScalar) - (PetscInt)((tmp3 - tmp1) % (align*sizeof(PetscScalar)))) % (align*sizeof(PetscScalar));
999306f9a3SSatish Balay   } else {
1009306f9a3SSatish Balay     tmp2  = (tmp1 - tmp3)/sizeof(PetscScalar);
1019306f9a3SSatish Balay     itmp2 = -((size_t) tmp2);
102f91d1997SBarry Smith     shift = (PetscInt)((tmp1 - tmp3) % (align*sizeof(PetscScalar)));
1039306f9a3SSatish Balay   }
1049306f9a3SSatish Balay #else
1059306f9a3SSatish Balay   if (tmp3 > tmp1) {  /* C is bigger than Fortran */
1069306f9a3SSatish Balay     tmp2  = (tmp3 - tmp1);
1079306f9a3SSatish Balay     itmp2 = (size_t) tmp2;
1089306f9a3SSatish Balay   } else {
1099306f9a3SSatish Balay     tmp2  = (tmp1 - tmp3);
1109306f9a3SSatish Balay     itmp2 = -((size_t) tmp2);
1119306f9a3SSatish Balay   }
1129306f9a3SSatish Balay   shift = 0;
1139306f9a3SSatish Balay #endif
1149306f9a3SSatish Balay 
1159306f9a3SSatish Balay   if (shift) {
1169306f9a3SSatish Balay     /*
1179306f9a3SSatish Balay         Fortran and C not PetscScalar aligned,recover by copying values into
1189306f9a3SSatish Balay         memory that is aligned with the Fortran
1199306f9a3SSatish Balay     */
1209306f9a3SSatish Balay     PetscErrorCode ierr;
1219306f9a3SSatish Balay     PetscScalar    *work;
122776b82aeSLisandro Dalcin     PetscContainer container;
1239306f9a3SSatish Balay 
124854ce69bSBarry Smith     ierr = PetscMalloc1(N+align,&work);CHKERRQ(ierr);
125f91d1997SBarry Smith 
126f91d1997SBarry Smith     /* recompute shift for newly allocated space */
127f91d1997SBarry Smith     tmp3 = (size_t) work;
128f91d1997SBarry Smith     if (tmp3 > tmp1) {  /* C is bigger than Fortran */
129f91d1997SBarry Smith       shift = (align*sizeof(PetscScalar) - (PetscInt)((tmp3 - tmp1) % (align*sizeof(PetscScalar)))) % (align*sizeof(PetscScalar));
130f91d1997SBarry Smith     } else {
131f91d1997SBarry Smith       shift = (PetscInt)((tmp1 - tmp3) % (align*sizeof(PetscScalar)));
132f91d1997SBarry Smith     }
1339306f9a3SSatish Balay 
1349306f9a3SSatish Balay     /* shift work by that number of bytes */
1359306f9a3SSatish Balay     work = (PetscScalar*)(((char*)work) + shift);
1369306f9a3SSatish Balay     ierr = PetscMemcpy(work,addr,N*sizeof(PetscScalar));CHKERRQ(ierr);
1379306f9a3SSatish Balay 
1389306f9a3SSatish Balay     /* store in the first location in addr how much you shift it */
1399306f9a3SSatish Balay     ((PetscInt*)addr)[0] = shift;
1409306f9a3SSatish Balay 
141776b82aeSLisandro Dalcin     ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr);
142776b82aeSLisandro Dalcin     ierr = PetscContainerSetPointer(container,addr);CHKERRQ(ierr);
1439306f9a3SSatish Balay     ierr = PetscObjectCompose(obj,"GetArrayPtr",(PetscObject)container);CHKERRQ(ierr);
1449306f9a3SSatish Balay 
1459306f9a3SSatish Balay     tmp3 = (size_t) work;
1469306f9a3SSatish Balay     if (tmp3 > tmp1) {  /* C is bigger than Fortran */
1479306f9a3SSatish Balay       tmp2  = (tmp3 - tmp1)/sizeof(PetscScalar);
1489306f9a3SSatish Balay       itmp2 = (size_t) tmp2;
149f91d1997SBarry Smith       shift = (align*sizeof(PetscScalar) - (PetscInt)((tmp3 - tmp1) % (align*sizeof(PetscScalar)))) % (align*sizeof(PetscScalar));
1509306f9a3SSatish Balay     } else {
1519306f9a3SSatish Balay       tmp2  = (tmp1 - tmp3)/sizeof(PetscScalar);
1529306f9a3SSatish Balay       itmp2 = -((size_t) tmp2);
153f91d1997SBarry Smith       shift = (PetscInt)((tmp1 - tmp3) % (align*sizeof(PetscScalar)));
1549306f9a3SSatish Balay     }
1559306f9a3SSatish Balay     if (shift) {
1569306f9a3SSatish Balay       (*PetscErrorPrintf)("PetscScalarAddressToFortran:C and Fortran arrays are\n");
1579306f9a3SSatish Balay       (*PetscErrorPrintf)("not commonly aligned.\n");
158bcaeba4dSBarry Smith       (*PetscErrorPrintf)("Locations/sizeof(PetscScalar): C %f Fortran %f\n",((PetscReal)tmp3)/(PetscReal)sizeof(PetscScalar),((PetscReal)tmp1)/(PetscReal)sizeof(PetscScalar));
1599306f9a3SSatish Balay       MPI_Abort(PETSC_COMM_WORLD,1);
1609306f9a3SSatish Balay     }
1611e2582c4SBarry Smith     ierr = PetscInfo(obj,"Efficiency warning, copying array in XXXGetArray() due\n\
162ae15b995SBarry Smith     to alignment differences between C and Fortran\n");CHKERRQ(ierr);
1639306f9a3SSatish Balay   }
1649306f9a3SSatish Balay   *res = itmp2;
1659306f9a3SSatish Balay   return 0;
1669306f9a3SSatish Balay }
1679306f9a3SSatish Balay 
1689306f9a3SSatish Balay /*
1699306f9a3SSatish Balay     obj - the PETSc object where the scalar pointer came from
1709306f9a3SSatish Balay     base - the Fortran array address
1719306f9a3SSatish Balay     addr - the Fortran offset from base
1729306f9a3SSatish Balay     N    - the amount of data
1739306f9a3SSatish Balay 
1749306f9a3SSatish Balay     lx   - the array space that is to be passed to XXXXRestoreArray()
1759306f9a3SSatish Balay */
1769306f9a3SSatish Balay PetscErrorCode PetscScalarAddressFromFortran(PetscObject obj,PetscScalar *base,size_t addr,PetscInt N,PetscScalar **lx)
1779306f9a3SSatish Balay {
1789306f9a3SSatish Balay   PetscErrorCode ierr;
1799306f9a3SSatish Balay   PetscInt       shift;
180776b82aeSLisandro Dalcin   PetscContainer container;
1819306f9a3SSatish Balay   PetscScalar    *tlx;
1829306f9a3SSatish Balay 
1839306f9a3SSatish Balay   ierr = PetscObjectQuery(obj,"GetArrayPtr",(PetscObject*)&container);CHKERRQ(ierr);
1849306f9a3SSatish Balay   if (container) {
185776b82aeSLisandro Dalcin     ierr = PetscContainerGetPointer(container,(void**)lx);CHKERRQ(ierr);
1869306f9a3SSatish Balay     tlx  = base + addr;
1879306f9a3SSatish Balay 
1889306f9a3SSatish Balay     shift = *(PetscInt*)*lx;
1899306f9a3SSatish Balay     ierr  = PetscMemcpy(*lx,tlx,N*sizeof(PetscScalar));CHKERRQ(ierr);
1909306f9a3SSatish Balay     tlx   = (PetscScalar*)(((char*)tlx) - shift);
191a297a907SKarl Rupp 
1929306f9a3SSatish Balay     ierr = PetscFree(tlx);CHKERRQ(ierr);
1936bf464f9SBarry Smith     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
1949306f9a3SSatish Balay     ierr = PetscObjectCompose(obj,"GetArrayPtr",0);CHKERRQ(ierr);
1959306f9a3SSatish Balay   } else {
1969306f9a3SSatish Balay     *lx = base + addr;
1979306f9a3SSatish Balay   }
1989306f9a3SSatish Balay   return 0;
1999306f9a3SSatish Balay }
2009306f9a3SSatish Balay 
20183886165SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
202f66fdb6dSSatish Balay #define petscisinfornanscalar_          PETSCISINFORNANSCALAR
203f66fdb6dSSatish Balay #define petscisinfornanreal_            PETSCISINFORNANREAL
20483886165SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
205f66fdb6dSSatish Balay #define petscisinfornanscalar_          petscisinfornanscalar
206f66fdb6dSSatish Balay #define petscisinfornanreal_            petscisinfornanreal
20783886165SBarry Smith #endif
20883886165SBarry Smith 
2098cc058d9SJed Brown PETSC_EXTERN PetscBool PETSC_STDCALL petscisinfornanscalar_(PetscScalar *v)
21083886165SBarry Smith {
211ace3abfcSBarry Smith   return (PetscBool) PetscIsInfOrNanScalar(*v);
212f66fdb6dSSatish Balay }
213f66fdb6dSSatish Balay 
2148cc058d9SJed Brown PETSC_EXTERN PetscBool PETSC_STDCALL petscisinfornanreal_(PetscReal *v)
215f66fdb6dSSatish Balay {
216ace3abfcSBarry Smith   return (PetscBool) PetscIsInfOrNanReal(*v);
21783886165SBarry Smith }
21883886165SBarry Smith 
21983886165SBarry Smith 
2209306f9a3SSatish Balay 
221