#include "private/fortranimpl.h" #include "petscmat.h" #if defined(PETSC_HAVE_FORTRAN_CAPS) #define matdestroymatrices_ MATDESTROYMATRICES #define matgetfactor_ MATGETFACTOR #define matfactorgetsolverpackage_ MATFACTORGETSOLVERPACKAGE #define matgetrowij_ MATGETROWIJ #define matrestorerowij_ MATRESTOREROWIJ #define matgetrow_ MATGETROW #define matrestorerow_ MATRESTOREROW #define matview_ MATVIEW #define matgetarray_ MATGETARRAY #define matrestorearray_ MATRESTOREARRAY #define matconvert_ MATCONVERT #define matgetsubmatrices_ MATGETSUBMATRICES #define matzerorows_ MATZEROROWS #define matzerorowsis_ MATZEROROWSIS #define matzerorowslocal_ MATZEROROWSLOCAL #define matzerorowslocalis_ MATZEROROWSLOCALIS #define matsetoptionsprefix_ MATSETOPTIONSPREFIX #define matgetvecs_ MATGETVECS #define matnullspaceremove_ MATNULLSPACEREMOV #define matgetinfo_ MATGETINFO #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) #define matdestroymatrices_ matdestroymatrices_ #define matgetfactor_ matgetfactor #define matfactorgetsolverpackage_ matfactorgetsolverpackage #define matgetvecs_ matgetvecs #define matgetrowij_ matgetrowij #define matrestorerowij_ matrestorerowij #define matgetrow_ matgetrow #define matrestorerow_ matrestorerow #define matview_ matview #define matgetarray_ matgetarray #define matrestorearray_ matrestorearray #define matconvert_ matconvert #define matgetsubmatrices_ matgetsubmatrices #define matzerorows_ matzerorows #define matzerorowsis_ matzerorowsis #define matzerorowslocal_ matzerorowslocal #define matzerorowslocalis_ matzerorowslocalis #define matsetoptionsprefix_ matsetoptionsprefix #define matnullspaceremove_ matnullspaceremove #define matgetinfo_ matgetinfo #endif EXTERN_C_BEGIN void PETSC_STDCALL matgetvecs_(Mat *mat,Vec *right,Vec *left, int *ierr ) { CHKFORTRANNULLOBJECT(right); CHKFORTRANNULLOBJECT(left); *ierr = MatGetVecs(*mat,right,left); } void PETSC_STDCALL matgetrowij_(Mat *B,PetscInt *shift,PetscTruth *sym,PetscTruth *blockcompressed,PetscInt *n,PetscInt *ia,size_t *iia, PetscInt *ja,size_t *jja,PetscTruth *done,PetscErrorCode *ierr) { PetscInt *IA,*JA; *ierr = MatGetRowIJ(*B,*shift,*sym,*blockcompressed,n,&IA,&JA,done);if (*ierr) return; *iia = PetscIntAddressToFortran(ia,IA); *jja = PetscIntAddressToFortran(ja,JA); } void PETSC_STDCALL matrestorerowij_(Mat *B,PetscInt *shift,PetscTruth *sym,PetscTruth *blockcompressed, PetscInt *n,PetscInt *ia,size_t *iia, PetscInt *ja,size_t *jja,PetscTruth *done,PetscErrorCode *ierr) { PetscInt *IA = PetscIntAddressFromFortran(ia,*iia),*JA = PetscIntAddressFromFortran(ja,*jja); *ierr = MatRestoreRowIJ(*B,*shift,*sym,*blockcompressed,n,&IA,&JA,done); } /* This is a poor way of storing the column and value pointers generated by MatGetRow() to be returned with MatRestoreRow() but there is not natural,good place else to store them. Hence Fortran programmers can only have one outstanding MatGetRows() at a time. */ static PetscErrorCode matgetrowactive = 0; static const PetscInt *my_ocols = 0; static const PetscScalar *my_ovals = 0; void PETSC_STDCALL matgetrow_(Mat *mat,PetscInt *row,PetscInt *ncols,PetscInt *cols,PetscScalar *vals,PetscErrorCode *ierr) { const PetscInt **oocols = &my_ocols; const PetscScalar **oovals = &my_ovals; if (matgetrowactive) { PetscError(__LINE__,"MatGetRow_Fortran",__FILE__,__SDIR__,1,0, "Cannot have two MatGetRow() active simultaneously\n\ call MatRestoreRow() before calling MatGetRow() a second time"); *ierr = 1; return; } CHKFORTRANNULLINTEGER(cols); if (!cols) oocols = PETSC_NULL; CHKFORTRANNULLSCALAR(vals); if (!vals) oovals = PETSC_NULL; *ierr = MatGetRow(*mat,*row,ncols,oocols,oovals); if (*ierr) return; if (oocols) { *ierr = PetscMemcpy(cols,my_ocols,(*ncols)*sizeof(PetscInt)); if (*ierr) return;} if (oovals) { *ierr = PetscMemcpy(vals,my_ovals,(*ncols)*sizeof(PetscScalar)); if (*ierr) return; } matgetrowactive = 1; } void PETSC_STDCALL matrestorerow_(Mat *mat,PetscInt *row,PetscInt *ncols,PetscInt *cols,PetscScalar *vals,PetscErrorCode *ierr) { const PetscInt **oocols = &my_ocols; const PetscScalar **oovals = &my_ovals; if (!matgetrowactive) { PetscError(__LINE__,"MatRestoreRow_Fortran",__FILE__,__SDIR__,1,0, "Must call MatGetRow() first"); *ierr = 1; return; } CHKFORTRANNULLINTEGER(cols); if (!cols) oocols = PETSC_NULL; CHKFORTRANNULLSCALAR(vals); if (!vals) oovals = PETSC_NULL; *ierr = MatRestoreRow(*mat,*row,ncols,oocols,oovals); matgetrowactive = 0; } void PETSC_STDCALL matview_(Mat *mat,PetscViewer *vin,PetscErrorCode *ierr) { PetscViewer v; PetscPatchDefaultViewers_Fortran(vin,v); *ierr = MatView(*mat,v); } void PETSC_STDCALL matgetarray_(Mat *mat,PetscScalar *fa,size_t *ia,PetscErrorCode *ierr) { PetscScalar *mm; PetscInt m,n; *ierr = MatGetArray(*mat,&mm); if (*ierr) return; *ierr = MatGetSize(*mat,&m,&n); if (*ierr) return; *ierr = PetscScalarAddressToFortran((PetscObject)*mat,1,fa,mm,m*n,ia); if (*ierr) return; } void PETSC_STDCALL matrestorearray_(Mat *mat,PetscScalar *fa,size_t *ia,PetscErrorCode *ierr) { PetscScalar *lx; PetscInt m,n; *ierr = MatGetSize(*mat,&m,&n); if (*ierr) return; *ierr = PetscScalarAddressFromFortran((PetscObject)*mat,fa,*ia,m*n,&lx);if (*ierr) return; *ierr = MatRestoreArray(*mat,&lx);if (*ierr) return; } void PETSC_STDCALL matfactorgetsolverpackage_(Mat *mat,CHAR name PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len)) { const char *tname; *ierr = MatFactorGetSolverPackage(*mat,&tname);if (*ierr) return; if (name != PETSC_NULL_CHARACTER_Fortran) { *ierr = PetscStrncpy(name,tname,len);if (*ierr) return; } FIXRETURNCHAR(PETSC_TRUE,name,len); } void PETSC_STDCALL matgetfactor_(Mat *mat,CHAR outtype PETSC_MIXED_LEN(len),MatFactorType ftype,Mat *M,PetscErrorCode *ierr PETSC_END_LEN(len)) { char *t; FIXCHAR(outtype,len,t); *ierr = MatGetFactor(*mat,t,ftype,M); FREECHAR(outtype,t); } void PETSC_STDCALL matconvert_(Mat *mat,CHAR outtype PETSC_MIXED_LEN(len),MatReuse *reuse,Mat *M,PetscErrorCode *ierr PETSC_END_LEN(len)) { char *t; FIXCHAR(outtype,len,t); *ierr = MatConvert(*mat,t,*reuse,M); FREECHAR(outtype,t); } /* MatGetSubmatrices() is slightly different from C since the Fortran provides the array to hold the submatrix objects,while in C that array is allocated by the MatGetSubmatrices() */ void PETSC_STDCALL matgetsubmatrices_(Mat *mat,PetscInt *n,IS *isrow,IS *iscol,MatReuse *scall,Mat *smat,PetscErrorCode *ierr) { Mat *lsmat; PetscInt i; if (*scall == MAT_INITIAL_MATRIX) { *ierr = MatGetSubMatrices(*mat,*n,isrow,iscol,*scall,&lsmat); for (i=0; i<*n; i++) { smat[i] = lsmat[i]; } *ierr = PetscFree(lsmat); } else { *ierr = MatGetSubMatrices(*mat,*n,isrow,iscol,*scall,&smat); } } /* MatDestroyMatrices() is slightly different from C since the Fortran provides the array to hold the submatrix objects,while in C that array is allocated by the MatGetSubmatrices() */ void PETSC_STDCALL matdestroymatrices_(Mat *mat,PetscInt *n,Mat *smat,PetscErrorCode *ierr) { PetscInt i; for (i=0; i<*n; i++) { *ierr = MatDestroy(smat[i]);if (*ierr) return; } } void PETSC_STDCALL matzerorows_(Mat *mat,PetscInt *numRows,PetscInt *rows,PetscScalar *diag,PetscErrorCode *ierr) { *ierr = MatZeroRows(*mat,*numRows,rows,*diag); } void PETSC_STDCALL matzerorowsis_(Mat *mat,IS *is,PetscScalar *diag,PetscErrorCode *ierr) { *ierr = MatZeroRowsIS(*mat,*is,*diag); } void PETSC_STDCALL matzerorowslocal_(Mat *mat,PetscInt *numRows,PetscInt *rows,PetscScalar *diag,PetscErrorCode *ierr) { *ierr = MatZeroRowsLocal(*mat,*numRows,rows,*diag); } void PETSC_STDCALL matzerorowslocalis_(Mat *mat,IS *is,PetscScalar *diag,PetscErrorCode *ierr) { *ierr = MatZeroRowsLocalIS(*mat,*is,*diag); } void PETSC_STDCALL matsetoptionsprefix_(Mat *mat,CHAR prefix PETSC_MIXED_LEN(len), PetscErrorCode *ierr PETSC_END_LEN(len)) { char *t; FIXCHAR(prefix,len,t); *ierr = MatSetOptionsPrefix(*mat,t); FREECHAR(prefix,t); } void PETSC_STDCALL matnullspaceremove_(MatNullSpace *sp,Vec *vec,Vec *out,PetscErrorCode *ierr) { CHKFORTRANNULLOBJECT(out); *ierr = MatNullSpaceRemove(*sp,*vec,out); } void PETSC_STDCALL matgetinfo_(Mat *mat,MatInfoType *flag,MatInfo *info, int *__ierr ) { *__ierr = MatGetInfo(*mat,*flag,info); } EXTERN_C_END