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 */ 289371c9d4SSatish Balay PetscErrorCode MatGetRootType_Private(Mat mat, MatType *rootType) { 292c99ec25SJunchao Zhang PetscBool found = PETSC_FALSE; 302c99ec25SJunchao Zhang MatRootName names = MatRootNameList; 312c99ec25SJunchao Zhang MatType inType; 322c99ec25SJunchao Zhang 332c99ec25SJunchao Zhang PetscFunctionBegin; 342c99ec25SJunchao Zhang PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 359566063dSJacob Faibussowitsch PetscCall(MatGetType(mat, &inType)); 362c99ec25SJunchao Zhang while (names) { 379566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(inType, names->mname, &found)); 389566063dSJacob Faibussowitsch if (!found) PetscCall(PetscStrcmp(inType, names->sname, &found)); 392c99ec25SJunchao Zhang if (found) { 402c99ec25SJunchao Zhang found = PETSC_TRUE; 412c99ec25SJunchao Zhang *rootType = names->rname; 422c99ec25SJunchao Zhang break; 432c99ec25SJunchao Zhang } 442c99ec25SJunchao Zhang names = names->next; 452c99ec25SJunchao Zhang } 462c99ec25SJunchao Zhang if (!found) *rootType = inType; 472c99ec25SJunchao Zhang PetscFunctionReturn(0); 482c99ec25SJunchao Zhang } 492c99ec25SJunchao Zhang 50ac81f253SRichard Tran Mills /* MatGetMPIMatType_Private - Gets the MPI type corresponding to the input matrix's type (e.g., MATMPIAIJ for MATSEQAIJ) 51ac81f253SRichard Tran Mills 52ac81f253SRichard Tran Mills Not Collective 53ac81f253SRichard Tran Mills 54ac81f253SRichard Tran Mills Input Parameters: 55ac81f253SRichard Tran Mills . mat - the input matrix, could be sequential or MPI 56ac81f253SRichard Tran Mills 57ac81f253SRichard Tran Mills Output Parameters: 58ac81f253SRichard Tran Mills . MPIType - the parallel (MPI) matrix type 59ac81f253SRichard Tran Mills 60ac81f253SRichard Tran Mills Level: developer 61ac81f253SRichard Tran Mills 62ac81f253SRichard Tran Mills .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat` 63ac81f253SRichard Tran Mills */ 649371c9d4SSatish Balay PetscErrorCode MatGetMPIMatType_Private(Mat mat, MatType *MPIType) { 65ac81f253SRichard Tran Mills PetscBool found = PETSC_FALSE; 66ac81f253SRichard Tran Mills MatRootName names = MatRootNameList; 67ac81f253SRichard Tran Mills MatType inType; 68ac81f253SRichard Tran Mills 69ac81f253SRichard Tran Mills PetscFunctionBegin; 70ac81f253SRichard Tran Mills PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 71ac81f253SRichard Tran Mills PetscCall(MatGetType(mat, &inType)); 72ac81f253SRichard Tran Mills while (names) { 73ac81f253SRichard Tran Mills PetscCall(PetscStrcmp(inType, names->sname, &found)); 74ac81f253SRichard Tran Mills if (!found) PetscCall(PetscStrcmp(inType, names->mname, &found)); 75ac81f253SRichard Tran Mills if (!found) PetscCall(PetscStrcmp(inType, names->rname, &found)); 76ac81f253SRichard Tran Mills if (found) { 77ac81f253SRichard Tran Mills found = PETSC_TRUE; 78ac81f253SRichard Tran Mills *MPIType = names->mname; 79ac81f253SRichard Tran Mills break; 80ac81f253SRichard Tran Mills } 81ac81f253SRichard Tran Mills names = names->next; 82ac81f253SRichard Tran Mills } 83ac81f253SRichard Tran Mills PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_SUP, "No corresponding parallel (MPI) type for this matrix"); 84ac81f253SRichard Tran Mills PetscFunctionReturn(0); 85ac81f253SRichard Tran Mills } 86ac81f253SRichard Tran Mills 877e14e8a7SBarry Smith /*@C 8899cd5145SBarry Smith MatSetType - Builds matrix object for a particular matrix type 897e14e8a7SBarry Smith 90*11a5261eSBarry Smith Collective on mat 917e14e8a7SBarry Smith 927e14e8a7SBarry Smith Input Parameters: 9399cd5145SBarry Smith + mat - the matrix object 9499cd5145SBarry Smith - matype - matrix type 957e14e8a7SBarry Smith 967e14e8a7SBarry Smith Options Database Key: 9799cd5145SBarry Smith . -mat_type <method> - Sets the type; use -help for a list 9899cd5145SBarry Smith of available methods (for instance, seqaij) 997e14e8a7SBarry Smith 100*11a5261eSBarry Smith Note: 10199cd5145SBarry Smith See "${PETSC_DIR}/include/petscmat.h" for available methods 1027e14e8a7SBarry Smith 1037e14e8a7SBarry Smith Level: intermediate 1047e14e8a7SBarry Smith 105db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 1067e14e8a7SBarry Smith @*/ 1079371c9d4SSatish Balay PetscErrorCode MatSetType(Mat mat, MatType matype) { 1083dcd2dd8SBarry Smith PetscBool sametype, found, subclass = PETSC_FALSE; 10923bebc0bSBarry Smith MatRootName names = MatRootNameList; 1105f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat); 1117e14e8a7SBarry Smith 1127e14e8a7SBarry Smith PetscFunctionBegin; 1130700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 114117016b1SBarry Smith 11501bebe75SBarry Smith while (names) { 1169566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(matype, names->rname, &found)); 11701bebe75SBarry Smith if (found) { 11801bebe75SBarry Smith PetscMPIInt size; 1199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 12001bebe75SBarry Smith if (size == 1) matype = names->sname; 12101bebe75SBarry Smith else matype = names->mname; 12201bebe75SBarry Smith break; 12301bebe75SBarry Smith } 12401bebe75SBarry Smith names = names->next; 12501bebe75SBarry Smith } 12601bebe75SBarry Smith 1279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype)); 12892ff6ae8SBarry Smith if (sametype) PetscFunctionReturn(0); 12992ff6ae8SBarry Smith 1309566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatList, matype, &r)); 1315f80ce2aSJacob Faibussowitsch PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype); 1327e14e8a7SBarry Smith 1339566063dSJacob Faibussowitsch if (mat->assembled && ((PetscObject)mat)->type_name) PetscCall(PetscStrbeginswith(matype, ((PetscObject)mat)->type_name, &subclass)); 1343dcd2dd8SBarry Smith if (subclass) { 1359566063dSJacob Faibussowitsch PetscCall(MatConvert(mat, matype, MAT_INPLACE_MATRIX, &mat)); 1363dcd2dd8SBarry Smith PetscFunctionReturn(0); 13728fc0bbcSJose E. Roman } 138dbbe0bcdSBarry Smith PetscTryTypeMethod(mat, destroy); 1390298fd71SBarry Smith mat->ops->destroy = NULL; 14082e0f345SBarry Smith 14132e7c8b0SBarry Smith /* should these null spaces be removed? */ 1429566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 1439566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 144dbbe0bcdSBarry Smith 1459566063dSJacob Faibussowitsch PetscCall(PetscMemzero(mat->ops, sizeof(struct _MatOps))); 14682e0f345SBarry Smith mat->preallocated = PETSC_FALSE; 14782e0f345SBarry Smith mat->assembled = PETSC_FALSE; 14882e0f345SBarry Smith mat->was_assembled = PETSC_FALSE; 14982e0f345SBarry Smith 15082e0f345SBarry Smith /* 15182e0f345SBarry Smith Increment, rather than reset these: the object is logically the same, so its logging and 15282e0f345SBarry Smith state is inherited. Furthermore, resetting makes it possible for the same state to be 15382e0f345SBarry Smith obtained with a different structure, confusing the PC. 15482e0f345SBarry Smith */ 15532e7c8b0SBarry Smith mat->nonzerostate++; 1569566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 157a2ec6df8SKris Buschelman 15835d8aa7fSBarry Smith /* create the new data structure */ 1599566063dSJacob Faibussowitsch PetscCall((*r)(mat)); 1607e14e8a7SBarry Smith PetscFunctionReturn(0); 1617e14e8a7SBarry Smith } 1627e14e8a7SBarry Smith 1637e14e8a7SBarry Smith /*@C 164f87b78b8SBarry Smith MatGetType - Gets the matrix type as a string from the matrix object. 1657e14e8a7SBarry Smith 1667e14e8a7SBarry Smith Not Collective 1677e14e8a7SBarry Smith 1687e14e8a7SBarry Smith Input Parameter: 16999cd5145SBarry Smith . mat - the matrix 1707e14e8a7SBarry Smith 1717e14e8a7SBarry Smith Output Parameter: 17299cd5145SBarry Smith . name - name of matrix type 1737e14e8a7SBarry Smith 1747e14e8a7SBarry Smith Level: intermediate 1757e14e8a7SBarry Smith 176*11a5261eSBarry Smith .seealso: `MatType`, `MatSetType()` 1777e14e8a7SBarry Smith @*/ 1789371c9d4SSatish Balay PetscErrorCode MatGetType(Mat mat, MatType *type) { 1797e14e8a7SBarry Smith PetscFunctionBegin; 1800700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 181c4e43342SLisandro Dalcin PetscValidPointer(type, 2); 1827adad957SLisandro Dalcin *type = ((PetscObject)mat)->type_name; 1837e14e8a7SBarry Smith PetscFunctionReturn(0); 1847e14e8a7SBarry Smith } 1857e14e8a7SBarry Smith 1860d229a57SStefano Zampini /*@C 187*11a5261eSBarry Smith MatGetVecType - Gets the vector type the matrix will return with `MatCreateVecs()` 1880d229a57SStefano Zampini 1890d229a57SStefano Zampini Not Collective 1900d229a57SStefano Zampini 1910d229a57SStefano Zampini Input Parameter: 1920d229a57SStefano Zampini . mat - the matrix 1930d229a57SStefano Zampini 1940d229a57SStefano Zampini Output Parameter: 1950d229a57SStefano Zampini . name - name of vector type 1960d229a57SStefano Zampini 1970d229a57SStefano Zampini Level: intermediate 1980d229a57SStefano Zampini 199*11a5261eSBarry Smith .seealso: `MatType`, `Mat`, `MatSetVecType()`, `VecType` 2000d229a57SStefano Zampini @*/ 2019371c9d4SSatish Balay PetscErrorCode MatGetVecType(Mat mat, VecType *vtype) { 2020d229a57SStefano Zampini PetscFunctionBegin; 2030d229a57SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2040d229a57SStefano Zampini PetscValidPointer(vtype, 2); 2050d229a57SStefano Zampini *vtype = mat->defaultvectype; 2060d229a57SStefano Zampini PetscFunctionReturn(0); 2070d229a57SStefano Zampini } 2080d229a57SStefano Zampini 2090d229a57SStefano Zampini /*@C 210*11a5261eSBarry Smith MatSetVecType - Set the vector type the matrix will return with `MatCreateVecs()` 2110d229a57SStefano Zampini 212*11a5261eSBarry Smith Collective on mat 2130d229a57SStefano Zampini 2140d229a57SStefano Zampini Input Parameters: 2150d229a57SStefano Zampini + mat - the matrix object 2160d229a57SStefano Zampini - vtype - vector type 2170d229a57SStefano Zampini 218*11a5261eSBarry Smith Note: 2190d229a57SStefano Zampini This is rarely needed in practice since each matrix object internally sets the proper vector type. 2200d229a57SStefano Zampini 2210d229a57SStefano Zampini Level: intermediate 2220d229a57SStefano Zampini 223*11a5261eSBarry Smith .seealso: `VecType`, `VecSetType()`, `MatGetVecType()` 2240d229a57SStefano Zampini @*/ 2259371c9d4SSatish Balay PetscErrorCode MatSetVecType(Mat mat, VecType vtype) { 2260d229a57SStefano Zampini PetscFunctionBegin; 2270d229a57SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2289566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->defaultvectype)); 2299566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(vtype, &mat->defaultvectype)); 2300d229a57SStefano Zampini PetscFunctionReturn(0); 2310d229a57SStefano Zampini } 2327e14e8a7SBarry Smith 2333cea93caSBarry Smith /*@C 2341c84c290SBarry Smith MatRegister - - Adds a new matrix type 2351c84c290SBarry Smith 2361c84c290SBarry Smith Not Collective 2371c84c290SBarry Smith 2381c84c290SBarry Smith Input Parameters: 2391c84c290SBarry Smith + name - name of a new user-defined matrix type 2401c84c290SBarry Smith - routine_create - routine to create method context 2411c84c290SBarry Smith 242*11a5261eSBarry Smith Note: 243*11a5261eSBarry Smith `MatRegister()` may be called multiple times to add several user-defined solvers. 2441c84c290SBarry Smith 2451c84c290SBarry Smith Sample usage: 2461c84c290SBarry Smith .vb 247bdf89e91SBarry Smith MatRegister("my_mat",MyMatCreate); 2481c84c290SBarry Smith .ve 2491c84c290SBarry Smith 2501c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via 2511c84c290SBarry Smith $ MatSetType(Mat,"my_mat") 2521c84c290SBarry Smith or at runtime via the option 2531c84c290SBarry Smith $ -mat_type my_mat 2541c84c290SBarry Smith 2551c84c290SBarry Smith Level: advanced 2561c84c290SBarry Smith 257*11a5261eSBarry Smith .seealso: `Mat`, `MatType`, `MatSetType()`, `MatRegisterAll()` 2583cea93caSBarry Smith @*/ 2599371c9d4SSatish Balay PetscErrorCode MatRegister(const char sname[], PetscErrorCode (*function)(Mat)) { 2607e14e8a7SBarry Smith PetscFunctionBegin; 2619566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2629566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatList, sname, function)); 26399cd5145SBarry Smith PetscFunctionReturn(0); 26499cd5145SBarry Smith } 26599cd5145SBarry Smith 266f4259b30SLisandro Dalcin MatRootName MatRootNameList = NULL; 26701bebe75SBarry Smith 26801bebe75SBarry Smith /*@C 269*11a5261eSBarry Smith MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. `MatSetType()` 27023bebc0bSBarry Smith and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the 27123bebc0bSBarry Smith matrix. 27201bebe75SBarry Smith 27301bebe75SBarry Smith Input Parameters: 274*11a5261eSBarry Smith + rname - the rootname, for example, `MATAIJ` 275*11a5261eSBarry Smith . sname - the name of the sequential matrix type, for example, `MATSEQAIJ` 276*11a5261eSBarry Smith - mname - the name of the parallel matrix type, for example, `MATMPIAIJ` 27701bebe75SBarry Smith 278*11a5261eSBarry Smith Note: 279*11a5261eSBarry Smith The matrix rootname should not be confused with the base type of the function `PetscObjectBaseTypeCompare()` 28001bebe75SBarry Smith 281*11a5261eSBarry Smith Developer Note: 282*11a5261eSBarry Smith PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate `VecType` based on the 283*11a5261eSBarry Smith size of the communicator but it is implemented by simply having additional `VecCreate_RootName()` registerer routines that dispatch to the 28423bebc0bSBarry Smith appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is 28523bebc0bSBarry Smith confusing. 28623bebc0bSBarry Smith 28723bebc0bSBarry Smith Level: developer 28823bebc0bSBarry Smith 289*11a5261eSBarry Smith .seealso: `Mat`, `MatType`, `PetscObjectBaseTypeCompare()` 29001bebe75SBarry Smith @*/ 2919371c9d4SSatish Balay PetscErrorCode MatRegisterRootName(const char rname[], const char sname[], const char mname[]) { 29223bebc0bSBarry Smith MatRootName names; 29301bebe75SBarry Smith 29401bebe75SBarry Smith PetscFunctionBegin; 2959566063dSJacob Faibussowitsch PetscCall(PetscNew(&names)); 2969566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rname, &names->rname)); 2979566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(sname, &names->sname)); 2989566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mname, &names->mname)); 29923bebc0bSBarry Smith if (!MatRootNameList) { 30023bebc0bSBarry Smith MatRootNameList = names; 30101bebe75SBarry Smith } else { 30223bebc0bSBarry Smith MatRootName next = MatRootNameList; 30301bebe75SBarry Smith while (next->next) next = next->next; 30401bebe75SBarry Smith next->next = names; 30501bebe75SBarry Smith } 30601bebe75SBarry Smith PetscFunctionReturn(0); 30701bebe75SBarry Smith } 308