1be1d678aSKris Buschelman 27e14e8a7SBarry Smith /* 399cd5145SBarry Smith Mechanism for register PETSc matrix types 47e14e8a7SBarry Smith */ 5af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 67e14e8a7SBarry Smith 7ace3abfcSBarry Smith PetscBool MatRegisterAllCalled = PETSC_FALSE; 87e14e8a7SBarry Smith 97e14e8a7SBarry Smith /* 1099cd5145SBarry Smith Contains the list of registered Mat routines 117e14e8a7SBarry Smith */ 12f4259b30SLisandro Dalcin PetscFunctionList MatList = NULL; 137e14e8a7SBarry Smith 142c99ec25SJunchao Zhang /* MatGetRootType_Private - Gets the root type of the input matrix's type (e.g., MATAIJ for MATSEQAIJ) 152c99ec25SJunchao Zhang 162c99ec25SJunchao Zhang Not Collective 172c99ec25SJunchao Zhang 182c99ec25SJunchao Zhang Input Parameters: 192c99ec25SJunchao Zhang . mat - the input matrix, could be sequential or MPI 202c99ec25SJunchao Zhang 212c99ec25SJunchao Zhang Output Parameters: 222c99ec25SJunchao Zhang . rootType - the root matrix type 232c99ec25SJunchao Zhang 242c99ec25SJunchao Zhang Level: developer 252c99ec25SJunchao Zhang 26db781477SPatrick Sanan .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat` 272c99ec25SJunchao Zhang */ 282c99ec25SJunchao Zhang PetscErrorCode MatGetRootType_Private(Mat mat, MatType *rootType) 292c99ec25SJunchao Zhang { 302c99ec25SJunchao Zhang PetscBool found = PETSC_FALSE; 312c99ec25SJunchao Zhang MatRootName names = MatRootNameList; 322c99ec25SJunchao Zhang MatType inType; 332c99ec25SJunchao Zhang 342c99ec25SJunchao Zhang PetscFunctionBegin; 352c99ec25SJunchao Zhang PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 369566063dSJacob Faibussowitsch PetscCall(MatGetType(mat,&inType)); 372c99ec25SJunchao Zhang while (names) { 389566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(inType,names->mname,&found)); 399566063dSJacob Faibussowitsch if (!found) PetscCall(PetscStrcmp(inType,names->sname,&found)); 402c99ec25SJunchao Zhang if (found) { 412c99ec25SJunchao Zhang found = PETSC_TRUE; 422c99ec25SJunchao Zhang *rootType = names->rname; 432c99ec25SJunchao Zhang break; 442c99ec25SJunchao Zhang } 452c99ec25SJunchao Zhang names = names->next; 462c99ec25SJunchao Zhang } 472c99ec25SJunchao Zhang if (!found) *rootType = inType; 482c99ec25SJunchao Zhang PetscFunctionReturn(0); 492c99ec25SJunchao Zhang } 502c99ec25SJunchao Zhang 51ac81f253SRichard Tran Mills /* MatGetMPIMatType_Private - Gets the MPI type corresponding to the input matrix's type (e.g., MATMPIAIJ for MATSEQAIJ) 52ac81f253SRichard Tran Mills 53ac81f253SRichard Tran Mills Not Collective 54ac81f253SRichard Tran Mills 55ac81f253SRichard Tran Mills Input Parameters: 56ac81f253SRichard Tran Mills . mat - the input matrix, could be sequential or MPI 57ac81f253SRichard Tran Mills 58ac81f253SRichard Tran Mills Output Parameters: 59ac81f253SRichard Tran Mills . MPIType - the parallel (MPI) matrix type 60ac81f253SRichard Tran Mills 61ac81f253SRichard Tran Mills Level: developer 62ac81f253SRichard Tran Mills 63ac81f253SRichard Tran Mills .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat` 64ac81f253SRichard Tran Mills */ 65ac81f253SRichard Tran Mills PetscErrorCode MatGetMPIMatType_Private(Mat mat, MatType *MPIType) 66ac81f253SRichard Tran Mills { 67ac81f253SRichard Tran Mills PetscBool found = PETSC_FALSE; 68ac81f253SRichard Tran Mills MatRootName names = MatRootNameList; 69ac81f253SRichard Tran Mills MatType inType; 70ac81f253SRichard Tran Mills 71ac81f253SRichard Tran Mills PetscFunctionBegin; 72ac81f253SRichard Tran Mills PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 73ac81f253SRichard Tran Mills PetscCall(MatGetType(mat,&inType)); 74ac81f253SRichard Tran Mills while (names) { 75ac81f253SRichard Tran Mills PetscCall(PetscStrcmp(inType,names->sname,&found)); 76ac81f253SRichard Tran Mills if (!found) PetscCall(PetscStrcmp(inType,names->mname,&found)); 77ac81f253SRichard Tran Mills if (!found) PetscCall(PetscStrcmp(inType,names->rname,&found)); 78ac81f253SRichard Tran Mills if (found) { 79ac81f253SRichard Tran Mills found = PETSC_TRUE; 80ac81f253SRichard Tran Mills *MPIType = names->mname; 81ac81f253SRichard Tran Mills break; 82ac81f253SRichard Tran Mills } 83ac81f253SRichard Tran Mills names = names->next; 84ac81f253SRichard Tran Mills } 85ac81f253SRichard Tran Mills PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_SUP,"No corresponding parallel (MPI) type for this matrix"); 86ac81f253SRichard Tran Mills PetscFunctionReturn(0); 87ac81f253SRichard Tran Mills } 88ac81f253SRichard Tran Mills 897e14e8a7SBarry Smith /*@C 9099cd5145SBarry Smith MatSetType - Builds matrix object for a particular matrix type 917e14e8a7SBarry Smith 9299cd5145SBarry Smith Collective on Mat 937e14e8a7SBarry Smith 947e14e8a7SBarry Smith Input Parameters: 9599cd5145SBarry Smith + mat - the matrix object 9699cd5145SBarry Smith - matype - matrix type 977e14e8a7SBarry Smith 987e14e8a7SBarry Smith Options Database Key: 9999cd5145SBarry Smith . -mat_type <method> - Sets the type; use -help for a list 10099cd5145SBarry Smith of available methods (for instance, seqaij) 1017e14e8a7SBarry Smith 1027e14e8a7SBarry Smith Notes: 10399cd5145SBarry Smith See "${PETSC_DIR}/include/petscmat.h" for available methods 1047e14e8a7SBarry Smith 1057e14e8a7SBarry Smith Level: intermediate 1067e14e8a7SBarry Smith 107db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 1087e14e8a7SBarry Smith @*/ 10919fd82e9SBarry Smith PetscErrorCode MatSetType(Mat mat, MatType matype) 1107e14e8a7SBarry Smith { 1113dcd2dd8SBarry Smith PetscBool sametype,found,subclass = PETSC_FALSE; 11223bebc0bSBarry Smith MatRootName names = MatRootNameList; 1135f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat); 1147e14e8a7SBarry Smith 1157e14e8a7SBarry Smith PetscFunctionBegin; 1160700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 117117016b1SBarry Smith 11801bebe75SBarry Smith while (names) { 1199566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(matype,names->rname,&found)); 12001bebe75SBarry Smith if (found) { 12101bebe75SBarry Smith PetscMPIInt size; 1229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size)); 12301bebe75SBarry Smith if (size == 1) matype = names->sname; 12401bebe75SBarry Smith else matype = names->mname; 12501bebe75SBarry Smith break; 12601bebe75SBarry Smith } 12701bebe75SBarry Smith names = names->next; 12801bebe75SBarry Smith } 12901bebe75SBarry Smith 1309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat,matype,&sametype)); 13192ff6ae8SBarry Smith if (sametype) PetscFunctionReturn(0); 13292ff6ae8SBarry Smith 1339566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatList,matype,&r)); 1345f80ce2aSJacob Faibussowitsch PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 1357e14e8a7SBarry Smith 1369566063dSJacob Faibussowitsch if (mat->assembled && ((PetscObject)mat)->type_name) PetscCall(PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass)); 1373dcd2dd8SBarry Smith if (subclass) { 1389566063dSJacob Faibussowitsch PetscCall(MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat)); 1393dcd2dd8SBarry Smith PetscFunctionReturn(0); 14028fc0bbcSJose E. Roman } 141*dbbe0bcdSBarry Smith PetscTryTypeMethod(mat,destroy); 1420298fd71SBarry Smith mat->ops->destroy = NULL; 14382e0f345SBarry Smith 14432e7c8b0SBarry Smith /* should these null spaces be removed? */ 1459566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 1469566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 147*dbbe0bcdSBarry Smith 1489566063dSJacob Faibussowitsch PetscCall(PetscMemzero(mat->ops,sizeof(struct _MatOps))); 14982e0f345SBarry Smith mat->preallocated = PETSC_FALSE; 15082e0f345SBarry Smith mat->assembled = PETSC_FALSE; 15182e0f345SBarry Smith mat->was_assembled = PETSC_FALSE; 15282e0f345SBarry Smith 15382e0f345SBarry Smith /* 15482e0f345SBarry Smith Increment, rather than reset these: the object is logically the same, so its logging and 15582e0f345SBarry Smith state is inherited. Furthermore, resetting makes it possible for the same state to be 15682e0f345SBarry Smith obtained with a different structure, confusing the PC. 15782e0f345SBarry Smith */ 15832e7c8b0SBarry Smith mat->nonzerostate++; 1599566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 160a2ec6df8SKris Buschelman 16135d8aa7fSBarry Smith /* create the new data structure */ 1629566063dSJacob Faibussowitsch PetscCall((*r)(mat)); 1637e14e8a7SBarry Smith PetscFunctionReturn(0); 1647e14e8a7SBarry Smith } 1657e14e8a7SBarry Smith 1667e14e8a7SBarry Smith /*@C 167f87b78b8SBarry Smith MatGetType - Gets the matrix type as a string from the matrix object. 1687e14e8a7SBarry Smith 1697e14e8a7SBarry Smith Not Collective 1707e14e8a7SBarry Smith 1717e14e8a7SBarry Smith Input Parameter: 17299cd5145SBarry Smith . mat - the matrix 1737e14e8a7SBarry Smith 1747e14e8a7SBarry Smith Output Parameter: 17599cd5145SBarry Smith . name - name of matrix type 1767e14e8a7SBarry Smith 1777e14e8a7SBarry Smith Level: intermediate 1787e14e8a7SBarry Smith 179db781477SPatrick Sanan .seealso: `MatSetType()` 1807e14e8a7SBarry Smith @*/ 18119fd82e9SBarry Smith PetscErrorCode MatGetType(Mat mat,MatType *type) 1827e14e8a7SBarry Smith { 1837e14e8a7SBarry Smith PetscFunctionBegin; 1840700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 185c4e43342SLisandro Dalcin PetscValidPointer(type,2); 1867adad957SLisandro Dalcin *type = ((PetscObject)mat)->type_name; 1877e14e8a7SBarry Smith PetscFunctionReturn(0); 1887e14e8a7SBarry Smith } 1897e14e8a7SBarry Smith 1900d229a57SStefano Zampini /*@C 1910d229a57SStefano Zampini MatGetVecType - Gets the vector type used by the matrix object. 1920d229a57SStefano Zampini 1930d229a57SStefano Zampini Not Collective 1940d229a57SStefano Zampini 1950d229a57SStefano Zampini Input Parameter: 1960d229a57SStefano Zampini . mat - the matrix 1970d229a57SStefano Zampini 1980d229a57SStefano Zampini Output Parameter: 1990d229a57SStefano Zampini . name - name of vector type 2000d229a57SStefano Zampini 2010d229a57SStefano Zampini Level: intermediate 2020d229a57SStefano Zampini 203db781477SPatrick Sanan .seealso: `MatSetVecType()` 2040d229a57SStefano Zampini @*/ 2050d229a57SStefano Zampini PetscErrorCode MatGetVecType(Mat mat,VecType *vtype) 2060d229a57SStefano Zampini { 2070d229a57SStefano Zampini PetscFunctionBegin; 2080d229a57SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2090d229a57SStefano Zampini PetscValidPointer(vtype,2); 2100d229a57SStefano Zampini *vtype = mat->defaultvectype; 2110d229a57SStefano Zampini PetscFunctionReturn(0); 2120d229a57SStefano Zampini } 2130d229a57SStefano Zampini 2140d229a57SStefano Zampini /*@C 2150d229a57SStefano Zampini MatSetVecType - Set the vector type to be used for a matrix object 2160d229a57SStefano Zampini 2170d229a57SStefano Zampini Collective on Mat 2180d229a57SStefano Zampini 2190d229a57SStefano Zampini Input Parameters: 2200d229a57SStefano Zampini + mat - the matrix object 2210d229a57SStefano Zampini - vtype - vector type 2220d229a57SStefano Zampini 2230d229a57SStefano Zampini Notes: 2240d229a57SStefano Zampini This is rarely needed in practice since each matrix object internally sets the proper vector type. 2250d229a57SStefano Zampini 2260d229a57SStefano Zampini Level: intermediate 2270d229a57SStefano Zampini 228db781477SPatrick Sanan .seealso: `VecSetType()`, `MatGetVecType()` 2290d229a57SStefano Zampini @*/ 2300d229a57SStefano Zampini PetscErrorCode MatSetVecType(Mat mat,VecType vtype) 2310d229a57SStefano Zampini { 2320d229a57SStefano Zampini PetscFunctionBegin; 2330d229a57SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2349566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->defaultvectype)); 2359566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(vtype,&mat->defaultvectype)); 2360d229a57SStefano Zampini PetscFunctionReturn(0); 2370d229a57SStefano Zampini } 2387e14e8a7SBarry Smith 2393cea93caSBarry Smith /*@C 2401c84c290SBarry Smith MatRegister - - Adds a new matrix type 2411c84c290SBarry Smith 2421c84c290SBarry Smith Not Collective 2431c84c290SBarry Smith 2441c84c290SBarry Smith Input Parameters: 2451c84c290SBarry Smith + name - name of a new user-defined matrix type 2461c84c290SBarry Smith - routine_create - routine to create method context 2471c84c290SBarry Smith 2481c84c290SBarry Smith Notes: 2491c84c290SBarry Smith MatRegister() may be called multiple times to add several user-defined solvers. 2501c84c290SBarry Smith 2511c84c290SBarry Smith Sample usage: 2521c84c290SBarry Smith .vb 253bdf89e91SBarry Smith MatRegister("my_mat",MyMatCreate); 2541c84c290SBarry Smith .ve 2551c84c290SBarry Smith 2561c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 2571c84c290SBarry Smith $ MatSetType(Mat,"my_mat") 2581c84c290SBarry Smith or at runtime via the option 2591c84c290SBarry Smith $ -mat_type my_mat 2601c84c290SBarry Smith 2611c84c290SBarry Smith Level: advanced 2621c84c290SBarry Smith 263db781477SPatrick Sanan .seealso: `MatRegisterAll()` 2641c84c290SBarry Smith 2657f6c08e0SMatthew Knepley Level: advanced 2663cea93caSBarry Smith @*/ 267bdf89e91SBarry Smith PetscErrorCode MatRegister(const char sname[],PetscErrorCode (*function)(Mat)) 2687e14e8a7SBarry Smith { 2697e14e8a7SBarry Smith PetscFunctionBegin; 2709566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2719566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatList,sname,function)); 27299cd5145SBarry Smith PetscFunctionReturn(0); 27399cd5145SBarry Smith } 27499cd5145SBarry Smith 275f4259b30SLisandro Dalcin MatRootName MatRootNameList = NULL; 27601bebe75SBarry Smith 27701bebe75SBarry Smith /*@C 27823bebc0bSBarry Smith MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType() 27923bebc0bSBarry Smith and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the 28023bebc0bSBarry Smith matrix. 28101bebe75SBarry Smith 28201bebe75SBarry Smith Input Parameters: 28323bebc0bSBarry Smith + rname - the rootname, for example, MATAIJ 28401bebe75SBarry Smith . sname - the name of the sequential matrix type, for example, MATSEQAIJ 28501bebe75SBarry Smith - mname - the name of the parallel matrix type, for example, MATMPIAIJ 28601bebe75SBarry Smith 28723bebc0bSBarry Smith Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare() 28801bebe75SBarry Smith 28923bebc0bSBarry Smith Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the 29023bebc0bSBarry Smith size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the 29123bebc0bSBarry Smith appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is 29223bebc0bSBarry Smith confusing. 29323bebc0bSBarry Smith 29423bebc0bSBarry Smith Level: developer 29523bebc0bSBarry Smith 296db781477SPatrick Sanan .seealso: `PetscObjectBaseTypeCompare()` 29723bebc0bSBarry Smith 29801bebe75SBarry Smith @*/ 29923bebc0bSBarry Smith PetscErrorCode MatRegisterRootName(const char rname[],const char sname[],const char mname[]) 30001bebe75SBarry Smith { 30123bebc0bSBarry Smith MatRootName names; 30201bebe75SBarry Smith 30301bebe75SBarry Smith PetscFunctionBegin; 3049566063dSJacob Faibussowitsch PetscCall(PetscNew(&names)); 3059566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rname,&names->rname)); 3069566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(sname,&names->sname)); 3079566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mname,&names->mname)); 30823bebc0bSBarry Smith if (!MatRootNameList) { 30923bebc0bSBarry Smith MatRootNameList = names; 31001bebe75SBarry Smith } else { 31123bebc0bSBarry Smith MatRootName next = MatRootNameList; 31201bebe75SBarry Smith while (next->next) next = next->next; 31301bebe75SBarry Smith next->next = names; 31401bebe75SBarry Smith } 31501bebe75SBarry Smith PetscFunctionReturn(0); 31601bebe75SBarry Smith } 317