1be1d678aSKris Buschelman 23b3e256bSKris Buschelman /* 3e3c5b3baSBarry Smith Provides an interface for the MATLAB engine sparse solver 43b3e256bSKris Buschelman 53b3e256bSKris Buschelman */ 6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h> 73b3e256bSKris Buschelman 8c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */ 9c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */ 103b3e256bSKris Buschelman 11aeeaa5c7SBarry Smith EXTERN_C_BEGIN 12aeeaa5c7SBarry Smith #undef __FUNCT__ 13aeeaa5c7SBarry Smith #define __FUNCT__ "MatSeqAIJToMatlab" 14aeeaa5c7SBarry Smith mxArray *MatSeqAIJToMatlab(Mat B) 15aeeaa5c7SBarry Smith { 16aeeaa5c7SBarry Smith PetscErrorCode ierr; 17aeeaa5c7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)B->data; 18c088a8dcSBarry Smith mwIndex *ii,*jj; 19aeeaa5c7SBarry Smith mxArray *mat; 20c088a8dcSBarry Smith PetscInt i; 21aeeaa5c7SBarry Smith 22aeeaa5c7SBarry Smith PetscFunctionBegin; 23aeeaa5c7SBarry Smith mat = mxCreateSparse(B->cmap->n,B->rmap->n,aij->nz,mxREAL); 24aeeaa5c7SBarry Smith ierr = PetscMemcpy(mxGetPr(mat),aij->a,aij->nz*sizeof(PetscScalar)); 25e3c5b3baSBarry Smith /* MATLAB stores by column, not row so we pass in the transpose of the matrix */ 26aeeaa5c7SBarry Smith jj = mxGetIr(mat); 27aeeaa5c7SBarry Smith for (i=0; i<aij->nz; i++) jj[i] = aij->j[i]; 28aeeaa5c7SBarry Smith ii = mxGetJc(mat); 29aeeaa5c7SBarry Smith for (i=0; i<B->rmap->n+1; i++) ii[i] = aij->i[i]; 30aeeaa5c7SBarry Smith PetscFunctionReturn(mat); 31aeeaa5c7SBarry Smith } 32aeeaa5c7SBarry Smith EXTERN_C_END 33aeeaa5c7SBarry Smith 34a1d52234SKris Buschelman 35a1d52234SKris Buschelman EXTERN_C_BEGIN 36a1d52234SKris Buschelman #undef __FUNCT__ 37b3866ffcSBarry Smith #define __FUNCT__ "MatlabEnginePut_SeqAIJ" 387087cfbeSBarry Smith PetscErrorCode MatlabEnginePut_SeqAIJ(PetscObject obj,void *mengine) 39a1d52234SKris Buschelman { 40dfbe8321SBarry Smith PetscErrorCode ierr; 41a1d52234SKris Buschelman mxArray *mat; 42a1d52234SKris Buschelman 43a1d52234SKris Buschelman PetscFunctionBegin; 44be6adb11SBarry Smith mat = MatSeqAIJToMatlab((Mat)obj);if (!mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create MATLAB matrix"); 45a1d52234SKris Buschelman ierr = PetscObjectName(obj);CHKERRQ(ierr); 46a1d52234SKris Buschelman engPutVariable((Engine*)mengine,obj->name,mat); 47a1d52234SKris Buschelman PetscFunctionReturn(0); 48a1d52234SKris Buschelman } 49a1d52234SKris Buschelman EXTERN_C_END 50a1d52234SKris Buschelman 51a1d52234SKris Buschelman EXTERN_C_BEGIN 52a1d52234SKris Buschelman #undef __FUNCT__ 53a7bb0f05SBarry Smith #define __FUNCT__ "MatSeqAIJFromMatlab" 5484c105d7SBarry Smith /*@C 55e3c5b3baSBarry Smith MatSeqAIJFromMatlab - Given a MATLAB sparse matrix, fills a SeqAIJ matrix with its transpose. 56a7bb0f05SBarry Smith 57a7bb0f05SBarry Smith Not Collective 58a7bb0f05SBarry Smith 59a7bb0f05SBarry Smith Input Parameters: 60e3c5b3baSBarry Smith + mmat - a MATLAB sparse matris 61a7bb0f05SBarry Smith - mat - a already created MATSEQAIJ 62a7bb0f05SBarry Smith 632bd2b0e6SSatish Balay Level: intermediate 642bd2b0e6SSatish Balay 65a7bb0f05SBarry Smith @*/ 667087cfbeSBarry Smith PetscErrorCode MatSeqAIJFromMatlab(mxArray *mmat,Mat mat) 67a1d52234SKris Buschelman { 68dfbe8321SBarry Smith PetscErrorCode ierr; 69b3da158bSBarry Smith PetscInt nz,n,m,*i,*j,k; 70b3da158bSBarry Smith mwIndex nnz,nn,nm,*ii,*jj; 71a1d52234SKris Buschelman Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 72a1d52234SKris Buschelman 73a1d52234SKris Buschelman PetscFunctionBegin; 74b3da158bSBarry Smith nn = mxGetN(mmat); /* rows of transpose of matrix */ 75b3da158bSBarry Smith nm = mxGetM(mmat); 76b3da158bSBarry Smith nnz = (mxGetJc(mmat))[nn]; 77b3da158bSBarry Smith ii = mxGetJc(mmat); 78b3da158bSBarry Smith jj = mxGetIr(mmat); 79b3da158bSBarry Smith n = (PetscInt) nn; 80b3da158bSBarry Smith m = (PetscInt) nm; 81b3da158bSBarry Smith nz = (PetscInt) nnz; 82b3da158bSBarry Smith 83b3da158bSBarry Smith if (mat->rmap->n < 0 && mat->cmap->n < 0) { 84b3da158bSBarry Smith /* matrix has not yet had its size set */ 85b3da158bSBarry Smith ierr = MatSetSizes(mat,n,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 864994cf47SJed Brown ierr = MatSetUp(mat);CHKERRQ(ierr); 87b3da158bSBarry Smith } else { 88b3da158bSBarry Smith if (mat->rmap->n != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change size of PETSc matrix %D to %D",mat->rmap->n,n); 89b3da158bSBarry Smith if (mat->cmap->n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change size of PETSc matrix %D to %D",mat->cmap->n,m); 90b3da158bSBarry Smith } 912eff7a51SBarry Smith if (nz != aij->nz) { 922eff7a51SBarry Smith /* number of nonzeros in matrix has changed, so need new data structure */ 931f03425eSSatish Balay ierr = MatSeqXAIJFreeAIJ(mat,&aij->a,&aij->j,&aij->i);CHKERRQ(ierr); 94b3da158bSBarry Smith aij->nz = nz; 95f0523c5fSHong Zhang ierr = PetscMalloc3(aij->nz,PetscScalar,&aij->a,aij->nz,PetscInt,&aij->j,mat->rmap->n+1,PetscInt,&aij->i);CHKERRQ(ierr); 96*2205254eSKarl Rupp 97a1d52234SKris Buschelman aij->singlemalloc = PETSC_TRUE; 982eff7a51SBarry Smith } 99a1d52234SKris Buschelman 100a1d52234SKris Buschelman ierr = PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));CHKERRQ(ierr); 101e3c5b3baSBarry Smith /* MATLAB stores by column, not row so we pass in the transpose of the matrix */ 102b3da158bSBarry Smith i = aij->i; 103*2205254eSKarl Rupp for (k=0; k<n+1; k++) i[k] = (PetscInt) ii[k]; 104b3da158bSBarry Smith j = aij->j; 105*2205254eSKarl Rupp for (k=0; k<nz; k++) j[k] = (PetscInt) jj[k]; 106a1d52234SKris Buschelman 107*2205254eSKarl Rupp for (k=0; k<mat->rmap->n; k++) aij->ilen[k] = aij->imax[k] = aij->i[k+1] - aij->i[k]; 108a1d52234SKris Buschelman 109a1d52234SKris Buschelman ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 110a1d52234SKris Buschelman ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 111a7bb0f05SBarry Smith PetscFunctionReturn(0); 112a7bb0f05SBarry Smith } 113a7bb0f05SBarry Smith EXTERN_C_END 114a1d52234SKris Buschelman 115a7bb0f05SBarry Smith 116a7bb0f05SBarry Smith EXTERN_C_BEGIN 117a7bb0f05SBarry Smith #undef __FUNCT__ 118a7bb0f05SBarry Smith #define __FUNCT__ "MatlabEngineGet_SeqAIJ" 1197087cfbeSBarry Smith PetscErrorCode MatlabEngineGet_SeqAIJ(PetscObject obj,void *mengine) 120a7bb0f05SBarry Smith { 121a7bb0f05SBarry Smith PetscErrorCode ierr; 122a7bb0f05SBarry Smith Mat mat = (Mat)obj; 123a7bb0f05SBarry Smith mxArray *mmat; 124a7bb0f05SBarry Smith 125a7bb0f05SBarry Smith PetscFunctionBegin; 126a7bb0f05SBarry Smith mmat = engGetVariable((Engine*)mengine,obj->name); 127a7bb0f05SBarry Smith ierr = MatSeqAIJFromMatlab(mmat,mat);CHKERRQ(ierr); 128a1d52234SKris Buschelman PetscFunctionReturn(0); 129a1d52234SKris Buschelman } 130a1d52234SKris Buschelman EXTERN_C_END 131a1d52234SKris Buschelman 13205db81ecSKris Buschelman #undef __FUNCT__ 13305db81ecSKris Buschelman #define __FUNCT__ "MatSolve_Matlab" 134dfbe8321SBarry Smith PetscErrorCode MatSolve_Matlab(Mat A,Vec b,Vec x) 1353b3e256bSKris Buschelman { 136dfbe8321SBarry Smith PetscErrorCode ierr; 137e060cb09SBarry Smith const char *_A,*_b,*_x; 1383b3e256bSKris Buschelman 1393b3e256bSKris Buschelman PetscFunctionBegin; 1403b3e256bSKris Buschelman /* make sure objects have names; use default if not */ 1413b3e256bSKris Buschelman ierr = PetscObjectName((PetscObject)b);CHKERRQ(ierr); 1423b3e256bSKris Buschelman ierr = PetscObjectName((PetscObject)x);CHKERRQ(ierr); 1433b3e256bSKris Buschelman 1443b3e256bSKris Buschelman ierr = PetscObjectGetName((PetscObject)A,&_A);CHKERRQ(ierr); 1453b3e256bSKris Buschelman ierr = PetscObjectGetName((PetscObject)b,&_b);CHKERRQ(ierr); 1463b3e256bSKris Buschelman ierr = PetscObjectGetName((PetscObject)x,&_x);CHKERRQ(ierr); 1477adad957SLisandro Dalcin ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)b);CHKERRQ(ierr); 1487adad957SLisandro Dalcin ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = u%s\\(l%s\\(p%s*%s));",_x,_A,_A,_A,_b);CHKERRQ(ierr); 1497adad957SLisandro Dalcin ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_b);CHKERRQ(ierr); 1507adad957SLisandro Dalcin /* ierr = PetscMatlabEnginePrintOutput(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),stdout);CHKERRQ(ierr); */ 1517adad957SLisandro Dalcin ierr = PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)x);CHKERRQ(ierr); 1523b3e256bSKris Buschelman PetscFunctionReturn(0); 1533b3e256bSKris Buschelman } 1543b3e256bSKris Buschelman 1553b3e256bSKris Buschelman #undef __FUNCT__ 15605db81ecSKris Buschelman #define __FUNCT__ "MatLUFactorNumeric_Matlab" 1570481f469SBarry Smith PetscErrorCode MatLUFactorNumeric_Matlab(Mat F,Mat A,const MatFactorInfo *info) 1583b3e256bSKris Buschelman { 159dfbe8321SBarry Smith PetscErrorCode ierr; 160de4209c5SBarry Smith size_t len; 1613b3e256bSKris Buschelman char *_A,*name; 162b3866ffcSBarry Smith PetscReal dtcol = info->dtcol; 1633b3e256bSKris Buschelman 1643b3e256bSKris Buschelman PetscFunctionBegin; 165d5f3da31SBarry Smith if (F->factortype == MAT_FACTOR_ILU || info->dt > 0) { 166b3866ffcSBarry Smith if (info->dtcol == PETSC_DEFAULT) dtcol = .01; 167fe97e370SBarry Smith F->ops->solve = MatSolve_Matlab; 168d5f3da31SBarry Smith F->factortype = MAT_FACTOR_LU; 169*2205254eSKarl Rupp 170fe97e370SBarry Smith ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)A);CHKERRQ(ierr); 171fe97e370SBarry Smith _A = ((PetscObject)A)->name; 172b3866ffcSBarry Smith ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"info_%s = struct('droptol',%g,'thresh',%g);",_A,info->dt,dtcol);CHKERRQ(ierr); 173fe97e370SBarry Smith ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"[l_%s,u_%s,p_%s] = luinc(%s',info_%s);",_A,_A,_A,_A,_A);CHKERRQ(ierr); 174fe97e370SBarry Smith ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_A);CHKERRQ(ierr); 175fe97e370SBarry Smith 176fe97e370SBarry Smith ierr = PetscStrlen(_A,&len);CHKERRQ(ierr); 177fe97e370SBarry Smith ierr = PetscMalloc((len+2)*sizeof(char),&name);CHKERRQ(ierr); 178fe97e370SBarry Smith sprintf(name,"_%s",_A); 179fe97e370SBarry Smith ierr = PetscObjectSetName((PetscObject)F,name);CHKERRQ(ierr); 180fe97e370SBarry Smith ierr = PetscFree(name);CHKERRQ(ierr); 181fe97e370SBarry Smith } else { 1827adad957SLisandro Dalcin ierr = PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),(PetscObject)A);CHKERRQ(ierr); 183f0523c5fSHong Zhang _A = ((PetscObject)A)->name; 184b3866ffcSBarry Smith ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"[l_%s,u_%s,p_%s] = lu(%s',%g);",_A,_A,_A,_A,dtcol);CHKERRQ(ierr); 1857adad957SLisandro Dalcin ierr = PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(((PetscObject)A)->comm),"%s = 0;",_A);CHKERRQ(ierr); 1863b3e256bSKris Buschelman ierr = PetscStrlen(_A,&len);CHKERRQ(ierr); 1873b3e256bSKris Buschelman ierr = PetscMalloc((len+2)*sizeof(char),&name);CHKERRQ(ierr); 1883b3e256bSKris Buschelman sprintf(name,"_%s",_A); 189f0523c5fSHong Zhang ierr = PetscObjectSetName((PetscObject)F,name);CHKERRQ(ierr); 1903b3e256bSKris Buschelman ierr = PetscFree(name);CHKERRQ(ierr); 191*2205254eSKarl Rupp 192f0523c5fSHong Zhang F->ops->solve = MatSolve_Matlab; 193fe97e370SBarry Smith } 1943b3e256bSKris Buschelman PetscFunctionReturn(0); 1953b3e256bSKris Buschelman } 1963b3e256bSKris Buschelman 1973b3e256bSKris Buschelman #undef __FUNCT__ 19805db81ecSKris Buschelman #define __FUNCT__ "MatLUFactorSymbolic_Matlab" 1990481f469SBarry Smith PetscErrorCode MatLUFactorSymbolic_Matlab(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 2003b3e256bSKris Buschelman { 2013b3e256bSKris Buschelman PetscFunctionBegin; 202e32f2f54SBarry Smith if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square"); 203f0523c5fSHong Zhang F->ops->lufactornumeric = MatLUFactorNumeric_Matlab; 204b3866ffcSBarry Smith F->assembled = PETSC_TRUE; 2053b3e256bSKris Buschelman PetscFunctionReturn(0); 2063b3e256bSKris Buschelman } 2073b3e256bSKris Buschelman 20835bd34faSBarry Smith EXTERN_C_BEGIN 20935bd34faSBarry Smith #undef __FUNCT__ 21035bd34faSBarry Smith #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_matlab" 21135bd34faSBarry Smith PetscErrorCode MatFactorGetSolverPackage_seqaij_matlab(Mat A,const MatSolverPackage *type) 21235bd34faSBarry Smith { 21335bd34faSBarry Smith PetscFunctionBegin; 2142692d6eeSBarry Smith *type = MATSOLVERMATLAB; 21535bd34faSBarry Smith PetscFunctionReturn(0); 21635bd34faSBarry Smith } 21735bd34faSBarry Smith EXTERN_C_END 21835bd34faSBarry Smith 2199402dedeSSatish Balay EXTERN_C_BEGIN 2203b3e256bSKris Buschelman #undef __FUNCT__ 221b24902e0SBarry Smith #define __FUNCT__ "MatGetFactor_seqaij_matlab" 2225c9eb25fSBarry Smith PetscErrorCode MatGetFactor_seqaij_matlab(Mat A,MatFactorType ftype,Mat *F) 2233b3e256bSKris Buschelman { 224dfbe8321SBarry Smith PetscErrorCode ierr; 2253b3e256bSKris Buschelman 2263b3e256bSKris Buschelman PetscFunctionBegin; 227e32f2f54SBarry Smith if (A->cmap->N != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"matrix must be square"); 2287adad957SLisandro Dalcin ierr = MatCreate(((PetscObject)A)->comm,F);CHKERRQ(ierr); 229f0523c5fSHong Zhang ierr = MatSetSizes(*F,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr); 2307adad957SLisandro Dalcin ierr = MatSetType(*F,((PetscObject)A)->type_name);CHKERRQ(ierr); 2313b3e256bSKris Buschelman ierr = MatSeqAIJSetPreallocation(*F,0,PETSC_NULL);CHKERRQ(ierr); 232b24902e0SBarry Smith (*F)->ops->lufactorsymbolic = MatLUFactorSymbolic_Matlab; 233b3866ffcSBarry Smith (*F)->ops->ilufactorsymbolic = MatLUFactorSymbolic_Matlab; 234*2205254eSKarl Rupp 235f75d6de4SMatthew Knepley ierr = PetscObjectComposeFunctionDynamic((PetscObject)(*F),"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_matlab",MatFactorGetSolverPackage_seqaij_matlab);CHKERRQ(ierr); 236f0523c5fSHong Zhang 237d5f3da31SBarry Smith (*F)->factortype = ftype; 2383b3e256bSKris Buschelman PetscFunctionReturn(0); 2393b3e256bSKris Buschelman } 2409402dedeSSatish Balay EXTERN_C_END 241b24902e0SBarry Smith 2423b3e256bSKris Buschelman /* --------------------------------------------------------------------------------*/ 2433b3e256bSKris Buschelman 24405db81ecSKris Buschelman #undef __FUNCT__ 24505db81ecSKris Buschelman #define __FUNCT__ "MatFactorInfo_Matlab" 246dfbe8321SBarry Smith PetscErrorCode MatFactorInfo_Matlab(Mat A,PetscViewer viewer) 2473b3e256bSKris Buschelman { 248dfbe8321SBarry Smith PetscErrorCode ierr; 2493b3e256bSKris Buschelman 2503b3e256bSKris Buschelman PetscFunctionBegin; 251e3c5b3baSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"MATLAB run parameters: -- not written yet!\n");CHKERRQ(ierr); 2523b3e256bSKris Buschelman PetscFunctionReturn(0); 2533b3e256bSKris Buschelman } 2543b3e256bSKris Buschelman 2553b3e256bSKris Buschelman #undef __FUNCT__ 25605db81ecSKris Buschelman #define __FUNCT__ "MatView_Matlab" 257b2d3331aSBarry Smith PetscErrorCode MatView_Matlab(Mat A,PetscViewer viewer) 258b2d3331aSBarry Smith { 259dfbe8321SBarry Smith PetscErrorCode ierr; 260ace3abfcSBarry Smith PetscBool iascii; 26105db81ecSKris Buschelman PetscViewerFormat format; 26205db81ecSKris Buschelman 26305db81ecSKris Buschelman PetscFunctionBegin; 264b24902e0SBarry Smith ierr = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr); 265251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 26632077d6dSBarry Smith if (iascii) { 26705db81ecSKris Buschelman ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 26805db81ecSKris Buschelman if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 26905db81ecSKris Buschelman ierr = MatFactorInfo_Matlab(A,viewer); 27005db81ecSKris Buschelman } 27105db81ecSKris Buschelman } 27205db81ecSKris Buschelman PetscFunctionReturn(0); 27305db81ecSKris Buschelman } 274f365a357SKris Buschelman 27505db81ecSKris Buschelman 27605db81ecSKris Buschelman /*MC 2772692d6eeSBarry Smith MATSOLVERMATLAB - "matlab" - Providing direct solvers (LU and QR) and drop tolerance 278e3c5b3baSBarry Smith based ILU factorization (ILUDT) for sequential matrices via the external package MATLAB. 27905db81ecSKris Buschelman 28005db81ecSKris Buschelman 28141c8de11SBarry Smith Works with MATSEQAIJ matrices. 28205db81ecSKris Buschelman 28305db81ecSKris Buschelman Options Database Keys: 284e3c5b3baSBarry Smith . -pc_factor_mat_solver_type matlab - selects MATLAB to do the sparse factorization 28541c8de11SBarry Smith 28605db81ecSKris Buschelman 28705db81ecSKris Buschelman Level: beginner 28805db81ecSKris Buschelman 28905db81ecSKris Buschelman .seealso: PCLU 29041c8de11SBarry Smith 29141c8de11SBarry Smith .seealso: PCFactorSetMatSolverPackage(), MatSolverPackage 29205db81ecSKris Buschelman M*/ 29305db81ecSKris Buschelman 294