1793850ffSBarry Smith 2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 3793850ffSBarry Smith 4f4259b30SLisandro Dalcin const char *const MatCompositeMergeTypes[] = {"left","right","MatCompositeMergeType","MAT_COMPOSITE_",NULL}; 58c8613bfSJakub Kruzik 6793850ffSBarry Smith typedef struct _Mat_CompositeLink *Mat_CompositeLink; 7793850ffSBarry Smith struct _Mat_CompositeLink { 8793850ffSBarry Smith Mat mat; 96d7c1e57SBarry Smith Vec work; 106d7c1e57SBarry Smith Mat_CompositeLink next,prev; 11793850ffSBarry Smith }; 12793850ffSBarry Smith 13793850ffSBarry Smith typedef struct { 146d7c1e57SBarry Smith MatCompositeType type; 156d7c1e57SBarry Smith Mat_CompositeLink head,tail; 16793850ffSBarry Smith Vec work; 17e4fc5df0SBarry Smith PetscScalar scale; /* scale factor supplied with MatScale() */ 18e4fc5df0SBarry Smith Vec left,right; /* left and right diagonal scaling provided with MatDiagonalScale() */ 1903049c21SJunchao Zhang Vec leftwork,rightwork,leftwork2,rightwork2; /* Two pairs of working vectors */ 206a7ede75SJakub Kruzik PetscInt nmat; 214b2558d6SJakub Kruzik PetscBool merge; 228c8613bfSJakub Kruzik MatCompositeMergeType mergetype; 233b35acafSJakub Kruzik MatStructure structure; 2403049c21SJunchao Zhang 2503049c21SJunchao Zhang PetscScalar *scalings; 2603049c21SJunchao Zhang PetscBool merge_mvctx; /* Whether need to merge mvctx of component matrices */ 2703049c21SJunchao Zhang Vec *lvecs; /* [nmat] Basically, they are Mvctx->lvec of each component matrix */ 2803049c21SJunchao Zhang PetscScalar *larray; /* [len] Data arrays of lvecs[] are stored consecutively in larray */ 2903049c21SJunchao Zhang PetscInt len; /* Length of larray[] */ 3003049c21SJunchao Zhang Vec gvec; /* Union of lvecs[] without duplicated entries */ 3103049c21SJunchao Zhang PetscInt *location; /* A map that maps entries in garray[] to larray[] */ 3203049c21SJunchao Zhang VecScatter Mvctx; 33793850ffSBarry Smith } Mat_Composite; 34793850ffSBarry Smith 35793850ffSBarry Smith PetscErrorCode MatDestroy_Composite(Mat mat) 36793850ffSBarry Smith { 37793850ffSBarry Smith PetscErrorCode ierr; 382c33bbaeSSatish Balay Mat_Composite *shell = (Mat_Composite*)mat->data; 396d7c1e57SBarry Smith Mat_CompositeLink next = shell->head,oldnext; 4003049c21SJunchao Zhang PetscInt i; 41793850ffSBarry Smith 42793850ffSBarry Smith PetscFunctionBegin; 43793850ffSBarry Smith while (next) { 446bf464f9SBarry Smith ierr = MatDestroy(&next->mat);CHKERRQ(ierr); 456d7c1e57SBarry Smith if (next->work && (!next->next || next->work != next->next->work)) { 466bf464f9SBarry Smith ierr = VecDestroy(&next->work);CHKERRQ(ierr); 476d7c1e57SBarry Smith } 486d7c1e57SBarry Smith oldnext = next; 49793850ffSBarry Smith next = next->next; 506d7c1e57SBarry Smith ierr = PetscFree(oldnext);CHKERRQ(ierr); 51793850ffSBarry Smith } 526bf464f9SBarry Smith ierr = VecDestroy(&shell->work);CHKERRQ(ierr); 536bf464f9SBarry Smith ierr = VecDestroy(&shell->left);CHKERRQ(ierr); 546bf464f9SBarry Smith ierr = VecDestroy(&shell->right);CHKERRQ(ierr); 556bf464f9SBarry Smith ierr = VecDestroy(&shell->leftwork);CHKERRQ(ierr); 566bf464f9SBarry Smith ierr = VecDestroy(&shell->rightwork);CHKERRQ(ierr); 5703049c21SJunchao Zhang ierr = VecDestroy(&shell->leftwork2);CHKERRQ(ierr); 5803049c21SJunchao Zhang ierr = VecDestroy(&shell->rightwork2);CHKERRQ(ierr); 5903049c21SJunchao Zhang 6003049c21SJunchao Zhang if (shell->Mvctx) { 6103049c21SJunchao Zhang for (i=0; i<shell->nmat; i++) {ierr = VecDestroy(&shell->lvecs[i]);CHKERRQ(ierr);} 6203049c21SJunchao Zhang ierr = PetscFree3(shell->location,shell->larray,shell->lvecs);CHKERRQ(ierr); 6303049c21SJunchao Zhang ierr = PetscFree(shell->larray);CHKERRQ(ierr); 6403049c21SJunchao Zhang ierr = VecDestroy(&shell->gvec);CHKERRQ(ierr); 6503049c21SJunchao Zhang ierr = VecScatterDestroy(&shell->Mvctx);CHKERRQ(ierr); 6603049c21SJunchao Zhang } 6703049c21SJunchao Zhang 6803049c21SJunchao Zhang ierr = PetscFree(shell->scalings);CHKERRQ(ierr); 696bf464f9SBarry Smith ierr = PetscFree(mat->data);CHKERRQ(ierr); 70793850ffSBarry Smith PetscFunctionReturn(0); 71793850ffSBarry Smith } 72793850ffSBarry Smith 736d7c1e57SBarry Smith PetscErrorCode MatMult_Composite_Multiplicative(Mat A,Vec x,Vec y) 746d7c1e57SBarry Smith { 756d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 766d7c1e57SBarry Smith Mat_CompositeLink next = shell->head; 776d7c1e57SBarry Smith PetscErrorCode ierr; 786d7c1e57SBarry Smith Vec in,out; 7903049c21SJunchao Zhang PetscScalar scale; 8003049c21SJunchao Zhang PetscInt i; 816d7c1e57SBarry Smith 826d7c1e57SBarry Smith PetscFunctionBegin; 83e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 846d7c1e57SBarry Smith in = x; 85e4fc5df0SBarry Smith if (shell->right) { 86e4fc5df0SBarry Smith if (!shell->rightwork) { 87e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 88e4fc5df0SBarry Smith } 89e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 90e4fc5df0SBarry Smith in = shell->rightwork; 91e4fc5df0SBarry Smith } 926d7c1e57SBarry Smith while (next->next) { 936d7c1e57SBarry Smith if (!next->work) { /* should reuse previous work if the same size */ 942a7a6963SBarry Smith ierr = MatCreateVecs(next->mat,NULL,&next->work);CHKERRQ(ierr); 956d7c1e57SBarry Smith } 966d7c1e57SBarry Smith out = next->work; 976d7c1e57SBarry Smith ierr = MatMult(next->mat,in,out);CHKERRQ(ierr); 986d7c1e57SBarry Smith in = out; 996d7c1e57SBarry Smith next = next->next; 1006d7c1e57SBarry Smith } 1016d7c1e57SBarry Smith ierr = MatMult(next->mat,in,y);CHKERRQ(ierr); 102e4fc5df0SBarry Smith if (shell->left) { 103e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr); 104e4fc5df0SBarry Smith } 10503049c21SJunchao Zhang scale = shell->scale; 10603049c21SJunchao Zhang if (shell->scalings) {for (i=0; i<shell->nmat; i++) scale *= shell->scalings[i];} 10703049c21SJunchao Zhang ierr = VecScale(y,scale);CHKERRQ(ierr); 1086d7c1e57SBarry Smith PetscFunctionReturn(0); 1096d7c1e57SBarry Smith } 1106d7c1e57SBarry Smith 1116d7c1e57SBarry Smith PetscErrorCode MatMultTranspose_Composite_Multiplicative(Mat A,Vec x,Vec y) 1126d7c1e57SBarry Smith { 1136d7c1e57SBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 1146d7c1e57SBarry Smith Mat_CompositeLink tail = shell->tail; 1156d7c1e57SBarry Smith PetscErrorCode ierr; 1166d7c1e57SBarry Smith Vec in,out; 11703049c21SJunchao Zhang PetscScalar scale; 11803049c21SJunchao Zhang PetscInt i; 1196d7c1e57SBarry Smith 1206d7c1e57SBarry Smith PetscFunctionBegin; 121e32f2f54SBarry Smith if (!tail) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 1226d7c1e57SBarry Smith in = x; 123e4fc5df0SBarry Smith if (shell->left) { 124e4fc5df0SBarry Smith if (!shell->leftwork) { 125e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 126e4fc5df0SBarry Smith } 127e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 128e4fc5df0SBarry Smith in = shell->leftwork; 129e4fc5df0SBarry Smith } 1306d7c1e57SBarry Smith while (tail->prev) { 1316d7c1e57SBarry Smith if (!tail->prev->work) { /* should reuse previous work if the same size */ 1322a7a6963SBarry Smith ierr = MatCreateVecs(tail->mat,NULL,&tail->prev->work);CHKERRQ(ierr); 1336d7c1e57SBarry Smith } 1346d7c1e57SBarry Smith out = tail->prev->work; 1356d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,out);CHKERRQ(ierr); 1366d7c1e57SBarry Smith in = out; 1376d7c1e57SBarry Smith tail = tail->prev; 1386d7c1e57SBarry Smith } 1396d7c1e57SBarry Smith ierr = MatMultTranspose(tail->mat,in,y);CHKERRQ(ierr); 140e4fc5df0SBarry Smith if (shell->right) { 141e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 142e4fc5df0SBarry Smith } 14303049c21SJunchao Zhang 14403049c21SJunchao Zhang scale = shell->scale; 14503049c21SJunchao Zhang if (shell->scalings) {for (i=0; i<shell->nmat; i++) scale *= shell->scalings[i];} 14603049c21SJunchao Zhang ierr = VecScale(y,scale);CHKERRQ(ierr); 1476d7c1e57SBarry Smith PetscFunctionReturn(0); 1486d7c1e57SBarry Smith } 1496d7c1e57SBarry Smith 15003049c21SJunchao Zhang PetscErrorCode MatMult_Composite(Mat mat,Vec x,Vec y) 151793850ffSBarry Smith { 152793850ffSBarry Smith PetscErrorCode ierr; 15303049c21SJunchao Zhang Mat_Composite *shell = (Mat_Composite*)mat->data; 15403049c21SJunchao Zhang Mat_CompositeLink cur = shell->head; 15503049c21SJunchao Zhang Vec in,y2,xin; 15603049c21SJunchao Zhang Mat A,B; 15703049c21SJunchao Zhang PetscInt i,j,k,n,nuniq,lo,hi,mid,*gindices,*buf,*tmp,tot; 15803049c21SJunchao Zhang const PetscScalar *vals; 15903049c21SJunchao Zhang const PetscInt *garray; 16003049c21SJunchao Zhang IS ix,iy; 16103049c21SJunchao Zhang PetscBool match; 162793850ffSBarry Smith 163793850ffSBarry Smith PetscFunctionBegin; 16403049c21SJunchao Zhang if (!cur) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 165e4fc5df0SBarry Smith in = x; 166e4fc5df0SBarry Smith if (shell->right) { 167e4fc5df0SBarry Smith if (!shell->rightwork) { 168e4fc5df0SBarry Smith ierr = VecDuplicate(shell->right,&shell->rightwork);CHKERRQ(ierr); 169793850ffSBarry Smith } 170e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->rightwork,shell->right,in);CHKERRQ(ierr); 171e4fc5df0SBarry Smith in = shell->rightwork; 172e4fc5df0SBarry Smith } 17303049c21SJunchao Zhang 17403049c21SJunchao Zhang /* Try to merge Mvctx when instructed but not yet done. We did not do it in MatAssemblyEnd() since at that time 17503049c21SJunchao Zhang we did not know whether mat is ADDITIVE or MULTIPLICATIVE. Only now we are assured mat is ADDITIVE and 17603049c21SJunchao Zhang it is legal to merge Mvctx, because all component matrices have the same size. 17703049c21SJunchao Zhang */ 17803049c21SJunchao Zhang if (shell->merge_mvctx && !shell->Mvctx) { 17903049c21SJunchao Zhang /* Currently only implemented for MATMPIAIJ */ 18003049c21SJunchao Zhang for (cur=shell->head; cur; cur=cur->next) { 18103049c21SJunchao Zhang ierr = PetscObjectTypeCompare((PetscObject)cur->mat,MATMPIAIJ,&match);CHKERRQ(ierr); 18203049c21SJunchao Zhang if (!match) { 18303049c21SJunchao Zhang shell->merge_mvctx = PETSC_FALSE; 18403049c21SJunchao Zhang goto skip_merge_mvctx; 185e4fc5df0SBarry Smith } 186e4fc5df0SBarry Smith } 18703049c21SJunchao Zhang 18803049c21SJunchao Zhang /* Go through matrices first time to count total number of nonzero off-diag columns (may have dups) */ 18903049c21SJunchao Zhang tot = 0; 19003049c21SJunchao Zhang for (cur=shell->head; cur; cur=cur->next) { 19103049c21SJunchao Zhang ierr = MatMPIAIJGetSeqAIJ(cur->mat,NULL,&B,NULL);CHKERRQ(ierr); 19203049c21SJunchao Zhang ierr = MatGetLocalSize(B,NULL,&n);CHKERRQ(ierr); 19303049c21SJunchao Zhang tot += n; 19403049c21SJunchao Zhang } 19503049c21SJunchao Zhang ierr = PetscMalloc3(tot,&shell->location,tot,&shell->larray,shell->nmat,&shell->lvecs);CHKERRQ(ierr); 19603049c21SJunchao Zhang shell->len = tot; 19703049c21SJunchao Zhang 19803049c21SJunchao Zhang /* Go through matrices second time to sort off-diag columns and remove dups */ 19903049c21SJunchao Zhang ierr = PetscMalloc1(tot,&gindices);CHKERRQ(ierr); /* No Malloc2() since we will give one to petsc and free the other */ 20003049c21SJunchao Zhang ierr = PetscMalloc1(tot,&buf);CHKERRQ(ierr); 20103049c21SJunchao Zhang nuniq = 0; /* Number of unique nonzero columns */ 20203049c21SJunchao Zhang for (cur=shell->head; cur; cur=cur->next) { 20303049c21SJunchao Zhang ierr = MatMPIAIJGetSeqAIJ(cur->mat,NULL,&B,&garray);CHKERRQ(ierr); 20403049c21SJunchao Zhang ierr = MatGetLocalSize(B,NULL,&n);CHKERRQ(ierr); 20503049c21SJunchao Zhang /* Merge pre-sorted garray[0,n) and gindices[0,nuniq) to buf[] */ 20603049c21SJunchao Zhang i = j = k = 0; 20703049c21SJunchao Zhang while (i < n && j < nuniq) { 20803049c21SJunchao Zhang if (garray[i] < gindices[j]) buf[k++] = garray[i++]; 20903049c21SJunchao Zhang else if (garray[i] > gindices[j]) buf[k++] = gindices[j++]; 21003049c21SJunchao Zhang else {buf[k++] = garray[i++]; j++;} 21103049c21SJunchao Zhang } 21203049c21SJunchao Zhang /* Copy leftover in garray[] or gindices[] */ 21303049c21SJunchao Zhang if (i < n) { 21403049c21SJunchao Zhang ierr = PetscArraycpy(buf+k,garray+i,n-i);CHKERRQ(ierr); 21503049c21SJunchao Zhang nuniq = k + n-i; 21603049c21SJunchao Zhang } else if (j < nuniq) { 21703049c21SJunchao Zhang ierr = PetscArraycpy(buf+k,gindices+j,nuniq-j);CHKERRQ(ierr); 21803049c21SJunchao Zhang nuniq = k + nuniq-j; 21903049c21SJunchao Zhang } else nuniq = k; 22003049c21SJunchao Zhang /* Swap gindices and buf to merge garray of the next matrix */ 22103049c21SJunchao Zhang tmp = gindices; 22203049c21SJunchao Zhang gindices = buf; 22303049c21SJunchao Zhang buf = tmp; 22403049c21SJunchao Zhang } 22503049c21SJunchao Zhang ierr = PetscFree(buf);CHKERRQ(ierr); 22603049c21SJunchao Zhang 22703049c21SJunchao Zhang /* Go through matrices third time to build a map from gindices[] to garray[] */ 22803049c21SJunchao Zhang tot = 0; 22903049c21SJunchao Zhang for (cur=shell->head,j=0; cur; cur=cur->next,j++) { /* j-th matrix */ 23003049c21SJunchao Zhang ierr = MatMPIAIJGetSeqAIJ(cur->mat,NULL,&B,&garray);CHKERRQ(ierr); 23103049c21SJunchao Zhang ierr = MatGetLocalSize(B,NULL,&n);CHKERRQ(ierr); 23203049c21SJunchao Zhang ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,n,NULL,&shell->lvecs[j]);CHKERRQ(ierr); 23303049c21SJunchao Zhang /* This is an optimized PetscFindInt(garray[i],nuniq,gindices,&shell->location[tot+i]), using the fact that garray[] is also sorted */ 23403049c21SJunchao Zhang lo = 0; 23503049c21SJunchao Zhang for (i=0; i<n; i++) { 23603049c21SJunchao Zhang hi = nuniq; 23703049c21SJunchao Zhang while (hi - lo > 1) { 23803049c21SJunchao Zhang mid = lo + (hi - lo)/2; 23903049c21SJunchao Zhang if (garray[i] < gindices[mid]) hi = mid; 24003049c21SJunchao Zhang else lo = mid; 24103049c21SJunchao Zhang } 24203049c21SJunchao Zhang shell->location[tot+i] = lo; /* gindices[lo] = garray[i] */ 24303049c21SJunchao Zhang lo++; /* Since garray[i+1] > garray[i], we can safely advance lo */ 24403049c21SJunchao Zhang } 24503049c21SJunchao Zhang tot += n; 24603049c21SJunchao Zhang } 24703049c21SJunchao Zhang 24803049c21SJunchao Zhang /* Build merged Mvctx */ 24903049c21SJunchao Zhang ierr = ISCreateGeneral(PETSC_COMM_SELF,nuniq,gindices,PETSC_OWN_POINTER,&ix);CHKERRQ(ierr); 25003049c21SJunchao Zhang ierr = ISCreateStride(PETSC_COMM_SELF,nuniq,0,1,&iy);CHKERRQ(ierr); 25103049c21SJunchao Zhang ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)mat),1,mat->cmap->n,mat->cmap->N,NULL,&xin);CHKERRQ(ierr); 25203049c21SJunchao Zhang ierr = VecCreateSeq(PETSC_COMM_SELF,nuniq,&shell->gvec);CHKERRQ(ierr); 25303049c21SJunchao Zhang ierr = VecScatterCreate(xin,ix,shell->gvec,iy,&shell->Mvctx);CHKERRQ(ierr); 25403049c21SJunchao Zhang ierr = VecDestroy(&xin);CHKERRQ(ierr); 25503049c21SJunchao Zhang ierr = ISDestroy(&ix);CHKERRQ(ierr); 25603049c21SJunchao Zhang ierr = ISDestroy(&iy);CHKERRQ(ierr); 25703049c21SJunchao Zhang } 25803049c21SJunchao Zhang 25903049c21SJunchao Zhang skip_merge_mvctx: 26003049c21SJunchao Zhang ierr = VecSet(y,0);CHKERRQ(ierr); 26103049c21SJunchao Zhang if (!shell->leftwork2) {ierr = VecDuplicate(y,&shell->leftwork2);CHKERRQ(ierr);} 26203049c21SJunchao Zhang y2 = shell->leftwork2; 26303049c21SJunchao Zhang 26403049c21SJunchao Zhang if (shell->Mvctx) { /* Have a merged Mvctx */ 26503049c21SJunchao Zhang /* Suppose we want to compute y = sMx, where s is the scaling factor and A, B are matrix M's diagonal/off-diagonal part. We could do 26603049c21SJunchao Zhang in y = s(Ax1 + Bx2) or y = sAx1 + sBx2. The former incurs less FLOPS than the latter, but the latter provides an oppertunity to 26703049c21SJunchao Zhang overlap communication/computation since we can do sAx1 while communicating x2. Here, we use the former approach. 26803049c21SJunchao Zhang */ 26903049c21SJunchao Zhang ierr = VecScatterBegin(shell->Mvctx,in,shell->gvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 27003049c21SJunchao Zhang ierr = VecScatterEnd(shell->Mvctx,in,shell->gvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 27103049c21SJunchao Zhang 27203049c21SJunchao Zhang ierr = VecGetArrayRead(shell->gvec,&vals);CHKERRQ(ierr); 27303049c21SJunchao Zhang for (i=0; i<shell->len; i++) shell->larray[i] = vals[shell->location[i]]; 27403049c21SJunchao Zhang ierr = VecRestoreArrayRead(shell->gvec,&vals);CHKERRQ(ierr); 27503049c21SJunchao Zhang 27603049c21SJunchao Zhang for (cur=shell->head,tot=i=0; cur; cur=cur->next,i++) { /* i-th matrix */ 27703049c21SJunchao Zhang ierr = MatMPIAIJGetSeqAIJ(cur->mat,&A,&B,NULL);CHKERRQ(ierr); 27803049c21SJunchao Zhang ierr = (*A->ops->mult)(A,in,y2);CHKERRQ(ierr); 27903049c21SJunchao Zhang ierr = MatGetLocalSize(B,NULL,&n);CHKERRQ(ierr); 28003049c21SJunchao Zhang ierr = VecPlaceArray(shell->lvecs[i],&shell->larray[tot]);CHKERRQ(ierr); 28103049c21SJunchao Zhang ierr = (*B->ops->multadd)(B,shell->lvecs[i],y2,y2);CHKERRQ(ierr); 28203049c21SJunchao Zhang ierr = VecResetArray(shell->lvecs[i]);CHKERRQ(ierr); 28303049c21SJunchao Zhang ierr = VecAXPY(y,(shell->scalings ? shell->scalings[i] : 1.0),y2);CHKERRQ(ierr); 28403049c21SJunchao Zhang tot += n; 28503049c21SJunchao Zhang } 28603049c21SJunchao Zhang } else { 28703049c21SJunchao Zhang if (shell->scalings) { 28803049c21SJunchao Zhang for (cur=shell->head,i=0; cur; cur=cur->next,i++) { 28903049c21SJunchao Zhang ierr = MatMult(cur->mat,in,y2);CHKERRQ(ierr); 29003049c21SJunchao Zhang ierr = VecAXPY(y,shell->scalings[i],y2);CHKERRQ(ierr); 29103049c21SJunchao Zhang } 29203049c21SJunchao Zhang } else { 29303049c21SJunchao Zhang for (cur=shell->head; cur; cur=cur->next) {ierr = MatMultAdd(cur->mat,in,y,y);CHKERRQ(ierr);} 29403049c21SJunchao Zhang } 29503049c21SJunchao Zhang } 29603049c21SJunchao Zhang 29703049c21SJunchao Zhang if (shell->left) {ierr = VecPointwiseMult(y,shell->left,y);CHKERRQ(ierr);} 298e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 299793850ffSBarry Smith PetscFunctionReturn(0); 300793850ffSBarry Smith } 301793850ffSBarry Smith 302793850ffSBarry Smith PetscErrorCode MatMultTranspose_Composite(Mat A,Vec x,Vec y) 303793850ffSBarry Smith { 304793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 305793850ffSBarry Smith Mat_CompositeLink next = shell->head; 306793850ffSBarry Smith PetscErrorCode ierr; 30703049c21SJunchao Zhang Vec in,y2 = NULL; 30803049c21SJunchao Zhang PetscInt i; 309793850ffSBarry Smith 310793850ffSBarry Smith PetscFunctionBegin; 311e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 312e4fc5df0SBarry Smith in = x; 313e4fc5df0SBarry Smith if (shell->left) { 314e4fc5df0SBarry Smith if (!shell->leftwork) { 315e4fc5df0SBarry Smith ierr = VecDuplicate(shell->left,&shell->leftwork);CHKERRQ(ierr); 316793850ffSBarry Smith } 317e4fc5df0SBarry Smith ierr = VecPointwiseMult(shell->leftwork,shell->left,in);CHKERRQ(ierr); 318e4fc5df0SBarry Smith in = shell->leftwork; 319e4fc5df0SBarry Smith } 32003049c21SJunchao Zhang 321e4fc5df0SBarry Smith ierr = MatMultTranspose(next->mat,in,y);CHKERRQ(ierr); 32203049c21SJunchao Zhang if (shell->scalings) { 32303049c21SJunchao Zhang ierr = VecScale(y,shell->scalings[0]);CHKERRQ(ierr); 32403049c21SJunchao Zhang if (!shell->rightwork2) {ierr = VecDuplicate(y,&shell->rightwork2);CHKERRQ(ierr);} 32503049c21SJunchao Zhang y2 = shell->rightwork2; 32603049c21SJunchao Zhang } 32703049c21SJunchao Zhang i = 1; 328e4fc5df0SBarry Smith while ((next = next->next)) { 32903049c21SJunchao Zhang if (!shell->scalings) {ierr = MatMultTransposeAdd(next->mat,in,y,y);CHKERRQ(ierr);} 33003049c21SJunchao Zhang else { 33103049c21SJunchao Zhang ierr = MatMultTranspose(next->mat,in,y2);CHKERRQ(ierr); 33203049c21SJunchao Zhang ierr = VecAXPY(y,shell->scalings[i++],y2);CHKERRQ(ierr); 33303049c21SJunchao Zhang } 334e4fc5df0SBarry Smith } 335e4fc5df0SBarry Smith if (shell->right) { 336e4fc5df0SBarry Smith ierr = VecPointwiseMult(y,shell->right,y);CHKERRQ(ierr); 337e4fc5df0SBarry Smith } 338e4fc5df0SBarry Smith ierr = VecScale(y,shell->scale);CHKERRQ(ierr); 339793850ffSBarry Smith PetscFunctionReturn(0); 340793850ffSBarry Smith } 341793850ffSBarry Smith 3427bf3a71bSJakub Kruzik PetscErrorCode MatMultAdd_Composite(Mat A,Vec x,Vec y,Vec z) 3437bf3a71bSJakub Kruzik { 3447bf3a71bSJakub Kruzik Mat_Composite *shell = (Mat_Composite*)A->data; 3457bf3a71bSJakub Kruzik PetscErrorCode ierr; 3467bf3a71bSJakub Kruzik 3477bf3a71bSJakub Kruzik PetscFunctionBegin; 3487bf3a71bSJakub Kruzik if (y != z) { 3497bf3a71bSJakub Kruzik ierr = MatMult(A,x,z);CHKERRQ(ierr); 3507bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr); 3517bf3a71bSJakub Kruzik } else { 3527bf3a71bSJakub Kruzik if (!shell->leftwork) { 3537bf3a71bSJakub Kruzik ierr = VecDuplicate(z,&shell->leftwork);CHKERRQ(ierr); 3547bf3a71bSJakub Kruzik } 3557bf3a71bSJakub Kruzik ierr = MatMult(A,x,shell->leftwork);CHKERRQ(ierr); 3567bf3a71bSJakub Kruzik ierr = VecCopy(y,z);CHKERRQ(ierr); 3577bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,shell->leftwork);CHKERRQ(ierr); 3587bf3a71bSJakub Kruzik } 3597bf3a71bSJakub Kruzik PetscFunctionReturn(0); 3607bf3a71bSJakub Kruzik } 3617bf3a71bSJakub Kruzik 3627bf3a71bSJakub Kruzik PetscErrorCode MatMultTransposeAdd_Composite(Mat A,Vec x,Vec y, Vec z) 3637bf3a71bSJakub Kruzik { 3647bf3a71bSJakub Kruzik Mat_Composite *shell = (Mat_Composite*)A->data; 3657bf3a71bSJakub Kruzik PetscErrorCode ierr; 3667bf3a71bSJakub Kruzik 3677bf3a71bSJakub Kruzik PetscFunctionBegin; 3687bf3a71bSJakub Kruzik if (y != z) { 3697bf3a71bSJakub Kruzik ierr = MatMultTranspose(A,x,z);CHKERRQ(ierr); 3707bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr); 3717bf3a71bSJakub Kruzik } else { 3727bf3a71bSJakub Kruzik if (!shell->rightwork) { 3737bf3a71bSJakub Kruzik ierr = VecDuplicate(z,&shell->rightwork);CHKERRQ(ierr); 3747bf3a71bSJakub Kruzik } 3757bf3a71bSJakub Kruzik ierr = MatMultTranspose(A,x,shell->rightwork);CHKERRQ(ierr); 3767bf3a71bSJakub Kruzik ierr = VecCopy(y,z);CHKERRQ(ierr); 3777bf3a71bSJakub Kruzik ierr = VecAXPY(z,1.0,shell->rightwork);CHKERRQ(ierr); 3787bf3a71bSJakub Kruzik } 3797bf3a71bSJakub Kruzik PetscFunctionReturn(0); 3807bf3a71bSJakub Kruzik } 3817bf3a71bSJakub Kruzik 382793850ffSBarry Smith PetscErrorCode MatGetDiagonal_Composite(Mat A,Vec v) 383793850ffSBarry Smith { 384793850ffSBarry Smith Mat_Composite *shell = (Mat_Composite*)A->data; 385793850ffSBarry Smith Mat_CompositeLink next = shell->head; 386793850ffSBarry Smith PetscErrorCode ierr; 38703049c21SJunchao Zhang PetscInt i; 388793850ffSBarry Smith 389793850ffSBarry Smith PetscFunctionBegin; 390e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 391e32f2f54SBarry Smith if (shell->right || shell->left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get diagonal if left or right scaling"); 392e4fc5df0SBarry Smith 393793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,v);CHKERRQ(ierr); 39403049c21SJunchao Zhang if (shell->scalings) {ierr = VecScale(v,shell->scalings[0]);CHKERRQ(ierr);} 39503049c21SJunchao Zhang 396793850ffSBarry Smith if (next->next && !shell->work) { 397793850ffSBarry Smith ierr = VecDuplicate(v,&shell->work);CHKERRQ(ierr); 398793850ffSBarry Smith } 39903049c21SJunchao Zhang i = 1; 400793850ffSBarry Smith while ((next = next->next)) { 401793850ffSBarry Smith ierr = MatGetDiagonal(next->mat,shell->work);CHKERRQ(ierr); 40203049c21SJunchao Zhang ierr = VecAXPY(v,(shell->scalings ? shell->scalings[i++] : 1.0),shell->work);CHKERRQ(ierr); 403793850ffSBarry Smith } 404e4fc5df0SBarry Smith ierr = VecScale(v,shell->scale);CHKERRQ(ierr); 405793850ffSBarry Smith PetscFunctionReturn(0); 406793850ffSBarry Smith } 407793850ffSBarry Smith 408793850ffSBarry Smith PetscErrorCode MatAssemblyEnd_Composite(Mat Y,MatAssemblyType t) 409793850ffSBarry Smith { 4104b2558d6SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)Y->data; 411b52f573bSBarry Smith PetscErrorCode ierr; 412b52f573bSBarry Smith 413793850ffSBarry Smith PetscFunctionBegin; 4144b2558d6SJakub Kruzik if (shell->merge) { 415b52f573bSBarry Smith ierr = MatCompositeMerge(Y);CHKERRQ(ierr); 416b52f573bSBarry Smith } 417793850ffSBarry Smith PetscFunctionReturn(0); 418793850ffSBarry Smith } 419793850ffSBarry Smith 420e4fc5df0SBarry Smith PetscErrorCode MatScale_Composite(Mat inA,PetscScalar alpha) 421e4fc5df0SBarry Smith { 422e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 423e4fc5df0SBarry Smith 424e4fc5df0SBarry Smith PetscFunctionBegin; 425321429dbSBarry Smith a->scale *= alpha; 426e4fc5df0SBarry Smith PetscFunctionReturn(0); 427e4fc5df0SBarry Smith } 428e4fc5df0SBarry Smith 429e4fc5df0SBarry Smith PetscErrorCode MatDiagonalScale_Composite(Mat inA,Vec left,Vec right) 430e4fc5df0SBarry Smith { 431e4fc5df0SBarry Smith Mat_Composite *a = (Mat_Composite*)inA->data; 432e4fc5df0SBarry Smith PetscErrorCode ierr; 433e4fc5df0SBarry Smith 434e4fc5df0SBarry Smith PetscFunctionBegin; 435e4fc5df0SBarry Smith if (left) { 436321429dbSBarry Smith if (!a->left) { 437e4fc5df0SBarry Smith ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr); 438e4fc5df0SBarry Smith ierr = VecCopy(left,a->left);CHKERRQ(ierr); 439321429dbSBarry Smith } else { 440321429dbSBarry Smith ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr); 441321429dbSBarry Smith } 442e4fc5df0SBarry Smith } 443e4fc5df0SBarry Smith if (right) { 444321429dbSBarry Smith if (!a->right) { 445e4fc5df0SBarry Smith ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr); 446e4fc5df0SBarry Smith ierr = VecCopy(right,a->right);CHKERRQ(ierr); 447321429dbSBarry Smith } else { 448321429dbSBarry Smith ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr); 449321429dbSBarry Smith } 450e4fc5df0SBarry Smith } 451e4fc5df0SBarry Smith PetscFunctionReturn(0); 452e4fc5df0SBarry Smith } 453793850ffSBarry Smith 4544b2558d6SJakub Kruzik PetscErrorCode MatSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,Mat A) 4554b2558d6SJakub Kruzik { 4564b2558d6SJakub Kruzik Mat_Composite *a = (Mat_Composite*)A->data; 4574b2558d6SJakub Kruzik PetscErrorCode ierr; 4584b2558d6SJakub Kruzik 4594b2558d6SJakub Kruzik PetscFunctionBegin; 4604b2558d6SJakub Kruzik ierr = PetscOptionsHead(PetscOptionsObject,"MATCOMPOSITE options");CHKERRQ(ierr); 4614b2558d6SJakub Kruzik ierr = PetscOptionsBool("-mat_composite_merge","Merge at MatAssemblyEnd","MatCompositeMerge",a->merge,&a->merge,NULL);CHKERRQ(ierr); 4628c8613bfSJakub Kruzik ierr = PetscOptionsEnum("-mat_composite_merge_type","Set composite merge direction","MatCompositeSetMergeType",MatCompositeMergeTypes,(PetscEnum)a->mergetype,(PetscEnum*)&a->mergetype,NULL);CHKERRQ(ierr); 46303049c21SJunchao Zhang ierr = PetscOptionsBool("-mat_composite_merge_mvctx","Merge MatMult() vecscat contexts","MatCreateComposite",a->merge_mvctx,&a->merge_mvctx,NULL);CHKERRQ(ierr); 4644b2558d6SJakub Kruzik ierr = PetscOptionsTail();CHKERRQ(ierr); 4654b2558d6SJakub Kruzik PetscFunctionReturn(0); 4664b2558d6SJakub Kruzik } 4674b2558d6SJakub Kruzik 4682c0821f3SBarry Smith /*@ 4698bd739bdSJakub Kruzik MatCreateComposite - Creates a matrix as the sum or product of one or more matrices 470793850ffSBarry Smith 471d083f849SBarry Smith Collective 472793850ffSBarry Smith 473793850ffSBarry Smith Input Parameters: 474793850ffSBarry Smith + comm - MPI communicator 475793850ffSBarry Smith . nmat - number of matrices to put in 476793850ffSBarry Smith - mats - the matrices 477793850ffSBarry Smith 478793850ffSBarry Smith Output Parameter: 479db36af27SMatthew G. Knepley . mat - the matrix 480793850ffSBarry Smith 4814b2558d6SJakub Kruzik Options Database Keys: 4824b2558d6SJakub Kruzik + -mat_composite_merge - merge in MatAssemblyEnd() 48303049c21SJunchao Zhang . -mat_composite_merge_mvctx - merge Mvctx of component matrices to optimize communication in MatMult() for ADDITIVE matrices 484b28d0daaSJakub Kruzik - -mat_composite_merge_type - set merge direction 4854b2558d6SJakub Kruzik 486793850ffSBarry Smith Level: advanced 487793850ffSBarry Smith 488793850ffSBarry Smith Notes: 489793850ffSBarry Smith Alternative construction 490793850ffSBarry Smith $ MatCreate(comm,&mat); 491793850ffSBarry Smith $ MatSetSizes(mat,m,n,M,N); 492793850ffSBarry Smith $ MatSetType(mat,MATCOMPOSITE); 493793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[0]); 494793850ffSBarry Smith $ .... 495793850ffSBarry Smith $ MatCompositeAddMat(mat,mats[nmat-1]); 496b52f573bSBarry Smith $ MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY); 497b52f573bSBarry Smith $ MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY); 498793850ffSBarry Smith 4996d7c1e57SBarry Smith For the multiplicative form the product is mat[nmat-1]*mat[nmat-2]*....*mat[0] 5006d7c1e57SBarry Smith 5016dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCompositeGetMat(), MatCompositeMerge(), MatCompositeSetType(), MATCOMPOSITE 502793850ffSBarry Smith 503793850ffSBarry Smith @*/ 5047087cfbeSBarry Smith PetscErrorCode MatCreateComposite(MPI_Comm comm,PetscInt nmat,const Mat *mats,Mat *mat) 505793850ffSBarry Smith { 506793850ffSBarry Smith PetscErrorCode ierr; 507793850ffSBarry Smith PetscInt m,n,M,N,i; 508793850ffSBarry Smith 509793850ffSBarry Smith PetscFunctionBegin; 510e32f2f54SBarry Smith if (nmat < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must pass in at least one matrix"); 511064a246eSJacob Faibussowitsch PetscValidPointer(mat,4); 512793850ffSBarry Smith 513c4f13f43SJakub Kruzik ierr = MatGetLocalSize(mats[0],PETSC_IGNORE,&n);CHKERRQ(ierr); 514c4f13f43SJakub Kruzik ierr = MatGetLocalSize(mats[nmat-1],&m,PETSC_IGNORE);CHKERRQ(ierr); 515c4f13f43SJakub Kruzik ierr = MatGetSize(mats[0],PETSC_IGNORE,&N);CHKERRQ(ierr); 516c4f13f43SJakub Kruzik ierr = MatGetSize(mats[nmat-1],&M,PETSC_IGNORE);CHKERRQ(ierr); 517793850ffSBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 518793850ffSBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 519793850ffSBarry Smith ierr = MatSetType(*mat,MATCOMPOSITE);CHKERRQ(ierr); 520793850ffSBarry Smith for (i=0; i<nmat; i++) { 521793850ffSBarry Smith ierr = MatCompositeAddMat(*mat,mats[i]);CHKERRQ(ierr); 522793850ffSBarry Smith } 523b52f573bSBarry Smith ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 524b52f573bSBarry Smith ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 525793850ffSBarry Smith PetscFunctionReturn(0); 526793850ffSBarry Smith } 527793850ffSBarry Smith 528d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeAddMat_Composite(Mat mat,Mat smat) 529d7f81bf2SJakub Kruzik { 530d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 531d7f81bf2SJakub Kruzik Mat_CompositeLink ilink,next = shell->head; 532d7f81bf2SJakub Kruzik PetscErrorCode ierr; 533d7f81bf2SJakub Kruzik 534d7f81bf2SJakub Kruzik PetscFunctionBegin; 535d7f81bf2SJakub Kruzik ierr = PetscNewLog(mat,&ilink);CHKERRQ(ierr); 536f4259b30SLisandro Dalcin ilink->next = NULL; 537d7f81bf2SJakub Kruzik ierr = PetscObjectReference((PetscObject)smat);CHKERRQ(ierr); 538d7f81bf2SJakub Kruzik ilink->mat = smat; 539d7f81bf2SJakub Kruzik 540d7f81bf2SJakub Kruzik if (!next) shell->head = ilink; 541d7f81bf2SJakub Kruzik else { 542d7f81bf2SJakub Kruzik while (next->next) { 543d7f81bf2SJakub Kruzik next = next->next; 544d7f81bf2SJakub Kruzik } 545d7f81bf2SJakub Kruzik next->next = ilink; 546d7f81bf2SJakub Kruzik ilink->prev = next; 547d7f81bf2SJakub Kruzik } 548d7f81bf2SJakub Kruzik shell->tail = ilink; 549d7f81bf2SJakub Kruzik shell->nmat += 1; 55003049c21SJunchao Zhang 55103049c21SJunchao Zhang /* Retain the old scalings (if any) and expand it with a 1.0 for the newly added matrix */ 55203049c21SJunchao Zhang if (shell->scalings) { 55303049c21SJunchao Zhang ierr = PetscRealloc(sizeof(PetscScalar)*shell->nmat,&shell->scalings);CHKERRQ(ierr); 55403049c21SJunchao Zhang shell->scalings[shell->nmat-1] = 1.0; 55503049c21SJunchao Zhang } 556d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 557d7f81bf2SJakub Kruzik } 558d7f81bf2SJakub Kruzik 559793850ffSBarry Smith /*@ 5608bd739bdSJakub Kruzik MatCompositeAddMat - Add another matrix to a composite matrix. 561793850ffSBarry Smith 562793850ffSBarry Smith Collective on Mat 563793850ffSBarry Smith 564793850ffSBarry Smith Input Parameters: 565793850ffSBarry Smith + mat - the composite matrix 566793850ffSBarry Smith - smat - the partial matrix 567793850ffSBarry Smith 568793850ffSBarry Smith Level: advanced 569793850ffSBarry Smith 5708bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE 571793850ffSBarry Smith @*/ 5727087cfbeSBarry Smith PetscErrorCode MatCompositeAddMat(Mat mat,Mat smat) 573793850ffSBarry Smith { 574793850ffSBarry Smith PetscErrorCode ierr; 575793850ffSBarry Smith 576793850ffSBarry Smith PetscFunctionBegin; 5770700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 5780700a824SBarry Smith PetscValidHeaderSpecific(smat,MAT_CLASSID,2); 579d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeAddMat_C",(Mat,Mat),(mat,smat));CHKERRQ(ierr); 580d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 581d7f81bf2SJakub Kruzik } 582793850ffSBarry Smith 583d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeSetType_Composite(Mat mat,MatCompositeType type) 584d7f81bf2SJakub Kruzik { 585d7f81bf2SJakub Kruzik Mat_Composite *b = (Mat_Composite*)mat->data; 586d7f81bf2SJakub Kruzik 587d7f81bf2SJakub Kruzik PetscFunctionBegin; 588ced1ac25SJakub Kruzik b->type = type; 589d7f81bf2SJakub Kruzik if (type == MAT_COMPOSITE_MULTIPLICATIVE) { 590f4259b30SLisandro Dalcin mat->ops->getdiagonal = NULL; 591d7f81bf2SJakub Kruzik mat->ops->mult = MatMult_Composite_Multiplicative; 592d7f81bf2SJakub Kruzik mat->ops->multtranspose = MatMultTranspose_Composite_Multiplicative; 59303049c21SJunchao Zhang b->merge_mvctx = PETSC_FALSE; 594d7f81bf2SJakub Kruzik } else { 595d7f81bf2SJakub Kruzik mat->ops->getdiagonal = MatGetDiagonal_Composite; 596d7f81bf2SJakub Kruzik mat->ops->mult = MatMult_Composite; 597d7f81bf2SJakub Kruzik mat->ops->multtranspose = MatMultTranspose_Composite; 598793850ffSBarry Smith } 5996d7c1e57SBarry Smith PetscFunctionReturn(0); 6006d7c1e57SBarry Smith } 6016d7c1e57SBarry Smith 6022c0821f3SBarry Smith /*@ 6038bd739bdSJakub Kruzik MatCompositeSetType - Indicates if the matrix is defined as the sum of a set of matrices or the product. 6046d7c1e57SBarry Smith 605b2b245abSJakub Kruzik Logically Collective on Mat 6066d7c1e57SBarry Smith 6076d7c1e57SBarry Smith Input Parameters: 6086d7c1e57SBarry Smith . mat - the composite matrix 6096d7c1e57SBarry Smith 6106d7c1e57SBarry Smith Level: advanced 6116d7c1e57SBarry Smith 6126dbc55e5SJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeGetType(), MATCOMPOSITE 6136d7c1e57SBarry Smith 6146d7c1e57SBarry Smith @*/ 6157087cfbeSBarry Smith PetscErrorCode MatCompositeSetType(Mat mat,MatCompositeType type) 6166d7c1e57SBarry Smith { 6176d7c1e57SBarry Smith PetscErrorCode ierr; 6186d7c1e57SBarry Smith 6196d7c1e57SBarry Smith PetscFunctionBegin; 620d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 621b2b245abSJakub Kruzik PetscValidLogicalCollectiveEnum(mat,type,2); 622d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeSetType_C",(Mat,MatCompositeType),(mat,type));CHKERRQ(ierr); 623793850ffSBarry Smith PetscFunctionReturn(0); 624793850ffSBarry Smith } 625793850ffSBarry Smith 6266dbc55e5SJakub Kruzik static PetscErrorCode MatCompositeGetType_Composite(Mat mat,MatCompositeType *type) 6276dbc55e5SJakub Kruzik { 6286dbc55e5SJakub Kruzik Mat_Composite *b = (Mat_Composite*)mat->data; 6296dbc55e5SJakub Kruzik 6306dbc55e5SJakub Kruzik PetscFunctionBegin; 6316dbc55e5SJakub Kruzik *type = b->type; 6326dbc55e5SJakub Kruzik PetscFunctionReturn(0); 6336dbc55e5SJakub Kruzik } 6346dbc55e5SJakub Kruzik 6356dbc55e5SJakub Kruzik /*@ 6366dbc55e5SJakub Kruzik MatCompositeGetType - Returns type of composite. 6376dbc55e5SJakub Kruzik 6386dbc55e5SJakub Kruzik Not Collective 6396dbc55e5SJakub Kruzik 6406dbc55e5SJakub Kruzik Input Parameter: 6416dbc55e5SJakub Kruzik . mat - the composite matrix 6426dbc55e5SJakub Kruzik 6436dbc55e5SJakub Kruzik Output Parameter: 6446dbc55e5SJakub Kruzik . type - type of composite 6456dbc55e5SJakub Kruzik 6466dbc55e5SJakub Kruzik Level: advanced 6476dbc55e5SJakub Kruzik 6486dbc55e5SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeSetType(), MATCOMPOSITE 6496dbc55e5SJakub Kruzik 6506dbc55e5SJakub Kruzik @*/ 6516dbc55e5SJakub Kruzik PetscErrorCode MatCompositeGetType(Mat mat,MatCompositeType *type) 6526dbc55e5SJakub Kruzik { 6536dbc55e5SJakub Kruzik PetscErrorCode ierr; 6546dbc55e5SJakub Kruzik 6556dbc55e5SJakub Kruzik PetscFunctionBegin; 6566dbc55e5SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 6576dbc55e5SJakub Kruzik PetscValidPointer(type,2); 6586dbc55e5SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeGetType_C",(Mat,MatCompositeType*),(mat,type));CHKERRQ(ierr); 6596dbc55e5SJakub Kruzik PetscFunctionReturn(0); 6606dbc55e5SJakub Kruzik } 6616dbc55e5SJakub Kruzik 6623b35acafSJakub Kruzik static PetscErrorCode MatCompositeSetMatStructure_Composite(Mat mat,MatStructure str) 6633b35acafSJakub Kruzik { 6643b35acafSJakub Kruzik Mat_Composite *b = (Mat_Composite*)mat->data; 6653b35acafSJakub Kruzik 6663b35acafSJakub Kruzik PetscFunctionBegin; 6673b35acafSJakub Kruzik b->structure = str; 6683b35acafSJakub Kruzik PetscFunctionReturn(0); 6693b35acafSJakub Kruzik } 6703b35acafSJakub Kruzik 6713b35acafSJakub Kruzik /*@ 6723b35acafSJakub Kruzik MatCompositeSetMatStructure - Indicates structure of matrices in the composite matrix. 6733b35acafSJakub Kruzik 6743b35acafSJakub Kruzik Not Collective 6753b35acafSJakub Kruzik 6763b35acafSJakub Kruzik Input Parameters: 6773b35acafSJakub Kruzik + mat - the composite matrix 6783b35acafSJakub Kruzik - str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN (default) or SUBSET_NONZERO_PATTERN 6793b35acafSJakub Kruzik 6803b35acafSJakub Kruzik Level: advanced 6813b35acafSJakub Kruzik 6823b35acafSJakub Kruzik Notes: 6833b35acafSJakub Kruzik Information about the matrices structure is used in MatCompositeMerge() for additive composite matrix. 6843b35acafSJakub Kruzik 6853b35acafSJakub Kruzik .seealso: MatAXPY(), MatCreateComposite(), MatCompositeMerge() MatCompositeGetMatStructure(), MATCOMPOSITE 6863b35acafSJakub Kruzik 6873b35acafSJakub Kruzik @*/ 6883b35acafSJakub Kruzik PetscErrorCode MatCompositeSetMatStructure(Mat mat,MatStructure str) 6893b35acafSJakub Kruzik { 6903b35acafSJakub Kruzik PetscErrorCode ierr; 6913b35acafSJakub Kruzik 6923b35acafSJakub Kruzik PetscFunctionBegin; 6933b35acafSJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 6943b35acafSJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeSetMatStructure_C",(Mat,MatStructure),(mat,str));CHKERRQ(ierr); 6953b35acafSJakub Kruzik PetscFunctionReturn(0); 6963b35acafSJakub Kruzik } 6973b35acafSJakub Kruzik 6983b35acafSJakub Kruzik static PetscErrorCode MatCompositeGetMatStructure_Composite(Mat mat,MatStructure *str) 6993b35acafSJakub Kruzik { 7003b35acafSJakub Kruzik Mat_Composite *b = (Mat_Composite*)mat->data; 7013b35acafSJakub Kruzik 7023b35acafSJakub Kruzik PetscFunctionBegin; 7033b35acafSJakub Kruzik *str = b->structure; 7043b35acafSJakub Kruzik PetscFunctionReturn(0); 7053b35acafSJakub Kruzik } 7063b35acafSJakub Kruzik 7073b35acafSJakub Kruzik /*@ 7083b35acafSJakub Kruzik MatCompositeGetMatStructure - Returns the structure of matrices in the composite matrix. 7093b35acafSJakub Kruzik 7103b35acafSJakub Kruzik Not Collective 7113b35acafSJakub Kruzik 7123b35acafSJakub Kruzik Input Parameter: 7133b35acafSJakub Kruzik . mat - the composite matrix 7143b35acafSJakub Kruzik 7153b35acafSJakub Kruzik Output Parameter: 7163b35acafSJakub Kruzik . str - structure of the matrices 7173b35acafSJakub Kruzik 7183b35acafSJakub Kruzik Level: advanced 7193b35acafSJakub Kruzik 7203b35acafSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeSetMatStructure(), MATCOMPOSITE 7213b35acafSJakub Kruzik 7223b35acafSJakub Kruzik @*/ 7233b35acafSJakub Kruzik PetscErrorCode MatCompositeGetMatStructure(Mat mat,MatStructure *str) 7243b35acafSJakub Kruzik { 7253b35acafSJakub Kruzik PetscErrorCode ierr; 7263b35acafSJakub Kruzik 7273b35acafSJakub Kruzik PetscFunctionBegin; 7283b35acafSJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 7293b35acafSJakub Kruzik PetscValidPointer(str,2); 7303b35acafSJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeGetMatStructure_C",(Mat,MatStructure*),(mat,str));CHKERRQ(ierr); 7313b35acafSJakub Kruzik PetscFunctionReturn(0); 7323b35acafSJakub Kruzik } 7333b35acafSJakub Kruzik 7348c8613bfSJakub Kruzik static PetscErrorCode MatCompositeSetMergeType_Composite(Mat mat,MatCompositeMergeType type) 7358c8613bfSJakub Kruzik { 7368c8613bfSJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 7378c8613bfSJakub Kruzik 7388c8613bfSJakub Kruzik PetscFunctionBegin; 7398c8613bfSJakub Kruzik shell->mergetype = type; 7408c8613bfSJakub Kruzik PetscFunctionReturn(0); 7418c8613bfSJakub Kruzik } 7428c8613bfSJakub Kruzik 7438c8613bfSJakub Kruzik /*@ 7448c8613bfSJakub Kruzik MatCompositeSetMergeType - Sets order of MatCompositeMerge(). 7458c8613bfSJakub Kruzik 7468c8613bfSJakub Kruzik Logically Collective on Mat 7478c8613bfSJakub Kruzik 748*d8d19677SJose E. Roman Input Parameters: 7498c8613bfSJakub Kruzik + mat - the composite matrix 7508c8613bfSJakub Kruzik - type - MAT_COMPOSITE_MERGE RIGHT (default) to start merge from right with the first added matrix (mat[0]), 7518c8613bfSJakub Kruzik MAT_COMPOSITE_MERGE_LEFT to start merge from left with the last added matrix (mat[nmat-1]) 7528c8613bfSJakub Kruzik 7538c8613bfSJakub Kruzik Level: advanced 7548c8613bfSJakub Kruzik 7558c8613bfSJakub Kruzik Notes: 7568c8613bfSJakub Kruzik The resulting matrix is the same regardles of the MergeType. Only the order of operation is changed. 7578c8613bfSJakub Kruzik If set to MAT_COMPOSITE_MERGE_RIGHT the order of the merge is mat[nmat-1]*(mat[nmat-2]*(...*(mat[1]*mat[0]))) 7588c8613bfSJakub Kruzik otherwise the order is (((mat[nmat-1]*mat[nmat-2])*mat[nmat-3])*...)*mat[0]. 7598c8613bfSJakub Kruzik 7608c8613bfSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeMerge(), MATCOMPOSITE 7618c8613bfSJakub Kruzik 7628c8613bfSJakub Kruzik @*/ 7638c8613bfSJakub Kruzik PetscErrorCode MatCompositeSetMergeType(Mat mat,MatCompositeMergeType type) 7648c8613bfSJakub Kruzik { 7658c8613bfSJakub Kruzik PetscErrorCode ierr; 7668c8613bfSJakub Kruzik 7678c8613bfSJakub Kruzik PetscFunctionBegin; 7688c8613bfSJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 7698c8613bfSJakub Kruzik PetscValidLogicalCollectiveEnum(mat,type,2); 7708c8613bfSJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeSetMergeType_C",(Mat,MatCompositeMergeType),(mat,type));CHKERRQ(ierr); 7718c8613bfSJakub Kruzik PetscFunctionReturn(0); 7728c8613bfSJakub Kruzik } 7738c8613bfSJakub Kruzik 774d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeMerge_Composite(Mat mat) 775b52f573bSBarry Smith { 776b52f573bSBarry Smith Mat_Composite *shell = (Mat_Composite*)mat->data; 7776d7c1e57SBarry Smith Mat_CompositeLink next = shell->head, prev = shell->tail; 778b52f573bSBarry Smith PetscErrorCode ierr; 7796d7c1e57SBarry Smith Mat tmat,newmat; 7801ba60692SJed Brown Vec left,right; 7811ba60692SJed Brown PetscScalar scale; 78203049c21SJunchao Zhang PetscInt i; 783b52f573bSBarry Smith 784b52f573bSBarry Smith PetscFunctionBegin; 785e32f2f54SBarry Smith if (!next) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must provide at least one matrix with MatCompositeAddMat()"); 78603049c21SJunchao Zhang scale = shell->scale; 7876d7c1e57SBarry Smith if (shell->type == MAT_COMPOSITE_ADDITIVE) { 7888c8613bfSJakub Kruzik if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) { 78903049c21SJunchao Zhang i = 0; 790b52f573bSBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 79103049c21SJunchao Zhang if (shell->scalings) {ierr = MatScale(tmat,shell->scalings[i++]);CHKERRQ(ierr);} 792b52f573bSBarry Smith while ((next = next->next)) { 79303049c21SJunchao Zhang ierr = MatAXPY(tmat,(shell->scalings ? shell->scalings[i++] : 1.0),next->mat,shell->structure);CHKERRQ(ierr); 794b52f573bSBarry Smith } 7956d7c1e57SBarry Smith } else { 79603049c21SJunchao Zhang i = shell->nmat-1; 7978c8613bfSJakub Kruzik ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 79803049c21SJunchao Zhang if (shell->scalings) {ierr = MatScale(tmat,shell->scalings[i--]);CHKERRQ(ierr);} 7998c8613bfSJakub Kruzik while ((prev = prev->prev)) { 80003049c21SJunchao Zhang ierr = MatAXPY(tmat,(shell->scalings ? shell->scalings[i--] : 1.0),prev->mat,shell->structure);CHKERRQ(ierr); 8018c8613bfSJakub Kruzik } 8028c8613bfSJakub Kruzik } 8038c8613bfSJakub Kruzik } else { 8048c8613bfSJakub Kruzik if (shell->mergetype == MAT_COMPOSITE_MERGE_RIGHT) { 8056d7c1e57SBarry Smith ierr = MatDuplicate(next->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 806b6cfcaf5SJakub Kruzik while ((next = next->next)) { 807b6cfcaf5SJakub Kruzik ierr = MatMatMult(next->mat,tmat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); 8086bf464f9SBarry Smith ierr = MatDestroy(&tmat);CHKERRQ(ierr); 8096d7c1e57SBarry Smith tmat = newmat; 8106d7c1e57SBarry Smith } 81104d534ceSJakub Kruzik } else { 81204d534ceSJakub Kruzik ierr = MatDuplicate(prev->mat,MAT_COPY_VALUES,&tmat);CHKERRQ(ierr); 81304d534ceSJakub Kruzik while ((prev = prev->prev)) { 81404d534ceSJakub Kruzik ierr = MatMatMult(tmat,prev->mat,MAT_INITIAL_MATRIX,PETSC_DECIDE,&newmat);CHKERRQ(ierr); 81504d534ceSJakub Kruzik ierr = MatDestroy(&tmat);CHKERRQ(ierr); 81604d534ceSJakub Kruzik tmat = newmat; 81704d534ceSJakub Kruzik } 81804d534ceSJakub Kruzik } 81903049c21SJunchao Zhang if (shell->scalings) {for (i=0; i<shell->nmat; i++) scale *= shell->scalings[i];} 8206d7c1e57SBarry Smith } 8211ba60692SJed Brown 8221ba60692SJed Brown if ((left = shell->left)) {ierr = PetscObjectReference((PetscObject)left);CHKERRQ(ierr);} 8231ba60692SJed Brown if ((right = shell->right)) {ierr = PetscObjectReference((PetscObject)right);CHKERRQ(ierr);} 8241ba60692SJed Brown 82528be2f97SBarry Smith ierr = MatHeaderReplace(mat,&tmat);CHKERRQ(ierr); 8261ba60692SJed Brown 8271ba60692SJed Brown ierr = MatDiagonalScale(mat,left,right);CHKERRQ(ierr); 8281ba60692SJed Brown ierr = MatScale(mat,scale);CHKERRQ(ierr); 8291ba60692SJed Brown ierr = VecDestroy(&left);CHKERRQ(ierr); 8301ba60692SJed Brown ierr = VecDestroy(&right);CHKERRQ(ierr); 831b52f573bSBarry Smith PetscFunctionReturn(0); 832b52f573bSBarry Smith } 8336a7ede75SJakub Kruzik 8346a7ede75SJakub Kruzik /*@ 835d7f81bf2SJakub Kruzik MatCompositeMerge - Given a composite matrix, replaces it with a "regular" matrix 8368bd739bdSJakub Kruzik by summing or computing the product of all the matrices inside the composite matrix. 837d7f81bf2SJakub Kruzik 838b2b245abSJakub Kruzik Collective 839d7f81bf2SJakub Kruzik 840d7f81bf2SJakub Kruzik Input Parameters: 841d7f81bf2SJakub Kruzik . mat - the composite matrix 842d7f81bf2SJakub Kruzik 8434b2558d6SJakub Kruzik Options Database Keys: 844b28d0daaSJakub Kruzik + -mat_composite_merge - merge in MatAssemblyEnd() 845b28d0daaSJakub Kruzik - -mat_composite_merge_type - set merge direction 846d7f81bf2SJakub Kruzik 847d7f81bf2SJakub Kruzik Level: advanced 848d7f81bf2SJakub Kruzik 849d7f81bf2SJakub Kruzik Notes: 850d7f81bf2SJakub Kruzik The MatType of the resulting matrix will be the same as the MatType of the FIRST 851d7f81bf2SJakub Kruzik matrix in the composite matrix. 852d7f81bf2SJakub Kruzik 8533b35acafSJakub Kruzik .seealso: MatDestroy(), MatMult(), MatCompositeAddMat(), MatCreateComposite(), MatCompositeSetMatStructure(), MatCompositeSetMergeType(), MATCOMPOSITE 854d7f81bf2SJakub Kruzik 855d7f81bf2SJakub Kruzik @*/ 856d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeMerge(Mat mat) 857d7f81bf2SJakub Kruzik { 858d7f81bf2SJakub Kruzik PetscErrorCode ierr; 859d7f81bf2SJakub Kruzik 860d7f81bf2SJakub Kruzik PetscFunctionBegin; 861d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 862d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeMerge_C",(Mat),(mat));CHKERRQ(ierr); 863d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 864d7f81bf2SJakub Kruzik } 865d7f81bf2SJakub Kruzik 8666d0add67SJakub Kruzik static PetscErrorCode MatCompositeGetNumberMat_Composite(Mat mat,PetscInt *nmat) 867d7f81bf2SJakub Kruzik { 868d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 869d7f81bf2SJakub Kruzik 870d7f81bf2SJakub Kruzik PetscFunctionBegin; 871d7f81bf2SJakub Kruzik *nmat = shell->nmat; 872d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 873d7f81bf2SJakub Kruzik } 874d7f81bf2SJakub Kruzik 875d7f81bf2SJakub Kruzik /*@ 8766d0add67SJakub Kruzik MatCompositeGetNumberMat - Returns the number of matrices in the composite matrix. 8776a7ede75SJakub Kruzik 8786a7ede75SJakub Kruzik Not Collective 8796a7ede75SJakub Kruzik 8806a7ede75SJakub Kruzik Input Parameter: 881d7f81bf2SJakub Kruzik . mat - the composite matrix 8826a7ede75SJakub Kruzik 8836a7ede75SJakub Kruzik Output Parameter: 8846d0add67SJakub Kruzik . nmat - number of matrices in the composite matrix 8856a7ede75SJakub Kruzik 8868b5c3584SJakub Kruzik Level: advanced 8876a7ede75SJakub Kruzik 8888bd739bdSJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetMat(), MATCOMPOSITE 8896a7ede75SJakub Kruzik 8906a7ede75SJakub Kruzik @*/ 8916d0add67SJakub Kruzik PetscErrorCode MatCompositeGetNumberMat(Mat mat,PetscInt *nmat) 8926a7ede75SJakub Kruzik { 893d7f81bf2SJakub Kruzik PetscErrorCode ierr; 8946a7ede75SJakub Kruzik 8956a7ede75SJakub Kruzik PetscFunctionBegin; 896d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 8976a7ede75SJakub Kruzik PetscValidPointer(nmat,2); 8986d0add67SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeGetNumberMat_C",(Mat,PetscInt*),(mat,nmat));CHKERRQ(ierr); 899d7f81bf2SJakub Kruzik PetscFunctionReturn(0); 900d7f81bf2SJakub Kruzik } 901d7f81bf2SJakub Kruzik 902d7f81bf2SJakub Kruzik static PetscErrorCode MatCompositeGetMat_Composite(Mat mat,PetscInt i,Mat *Ai) 903d7f81bf2SJakub Kruzik { 904d7f81bf2SJakub Kruzik Mat_Composite *shell = (Mat_Composite*)mat->data; 905d7f81bf2SJakub Kruzik Mat_CompositeLink ilink; 906d7f81bf2SJakub Kruzik PetscInt k; 907d7f81bf2SJakub Kruzik 908d7f81bf2SJakub Kruzik PetscFunctionBegin; 909d7f81bf2SJakub Kruzik if (i >= shell->nmat) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_OUTOFRANGE,"index out of range: %d >= %d",i,shell->nmat); 910d7f81bf2SJakub Kruzik ilink = shell->head; 911d7f81bf2SJakub Kruzik for (k=0; k<i; k++) { 912d7f81bf2SJakub Kruzik ilink = ilink->next; 913d7f81bf2SJakub Kruzik } 914d7f81bf2SJakub Kruzik *Ai = ilink->mat; 9156a7ede75SJakub Kruzik PetscFunctionReturn(0); 9166a7ede75SJakub Kruzik } 9176a7ede75SJakub Kruzik 9188b5c3584SJakub Kruzik /*@ 9198bd739bdSJakub Kruzik MatCompositeGetMat - Returns the ith matrix from the composite matrix. 9208b5c3584SJakub Kruzik 9218b5c3584SJakub Kruzik Logically Collective on Mat 9228b5c3584SJakub Kruzik 923*d8d19677SJose E. Roman Input Parameters: 924d7f81bf2SJakub Kruzik + mat - the composite matrix 9258b5c3584SJakub Kruzik - i - the number of requested matrix 9268b5c3584SJakub Kruzik 9278b5c3584SJakub Kruzik Output Parameter: 9288b5c3584SJakub Kruzik . Ai - ith matrix in composite 9298b5c3584SJakub Kruzik 9308b5c3584SJakub Kruzik Level: advanced 9318b5c3584SJakub Kruzik 9326d0add67SJakub Kruzik .seealso: MatCreateComposite(), MatCompositeGetNumberMat(), MatCompositeAddMat(), MATCOMPOSITE 9338b5c3584SJakub Kruzik 9348b5c3584SJakub Kruzik @*/ 935d7f81bf2SJakub Kruzik PetscErrorCode MatCompositeGetMat(Mat mat,PetscInt i,Mat *Ai) 9368b5c3584SJakub Kruzik { 937d7f81bf2SJakub Kruzik PetscErrorCode ierr; 9388b5c3584SJakub Kruzik 9398b5c3584SJakub Kruzik PetscFunctionBegin; 940d7f81bf2SJakub Kruzik PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 941d7f81bf2SJakub Kruzik PetscValidLogicalCollectiveInt(mat,i,2); 9428b5c3584SJakub Kruzik PetscValidPointer(Ai,3); 943d7f81bf2SJakub Kruzik ierr = PetscUseMethod(mat,"MatCompositeGetMat_C",(Mat,PetscInt,Mat*),(mat,i,Ai));CHKERRQ(ierr); 9448b5c3584SJakub Kruzik PetscFunctionReturn(0); 9458b5c3584SJakub Kruzik } 9468b5c3584SJakub Kruzik 94703049c21SJunchao Zhang PetscErrorCode MatCompositeSetScalings_Composite(Mat mat,const PetscScalar *scalings) 94803049c21SJunchao Zhang { 94903049c21SJunchao Zhang PetscErrorCode ierr; 95003049c21SJunchao Zhang Mat_Composite *shell = (Mat_Composite*)mat->data; 95103049c21SJunchao Zhang PetscInt nmat; 95203049c21SJunchao Zhang 95303049c21SJunchao Zhang PetscFunctionBegin; 95403049c21SJunchao Zhang ierr = MatCompositeGetNumberMat(mat,&nmat);CHKERRQ(ierr); 95503049c21SJunchao Zhang if (!shell->scalings) {ierr = PetscMalloc1(nmat,&shell->scalings);CHKERRQ(ierr);} 95603049c21SJunchao Zhang ierr = PetscArraycpy(shell->scalings,scalings,nmat);CHKERRQ(ierr); 95703049c21SJunchao Zhang PetscFunctionReturn(0); 95803049c21SJunchao Zhang } 95903049c21SJunchao Zhang 96003049c21SJunchao Zhang /*@ 96103049c21SJunchao Zhang MatCompositeSetScalings - Sets separate scaling factors for component matrices. 96203049c21SJunchao Zhang 96303049c21SJunchao Zhang Logically Collective on Mat 96403049c21SJunchao Zhang 965*d8d19677SJose E. Roman Input Parameters: 96603049c21SJunchao Zhang + mat - the composite matrix 96703049c21SJunchao Zhang - scalings - array of scaling factors with scalings[i] being factor of i-th matrix, for i in [0, nmat) 96803049c21SJunchao Zhang 96903049c21SJunchao Zhang Level: advanced 97003049c21SJunchao Zhang 97103049c21SJunchao Zhang .seealso: MatScale(), MatDiagonalScale(), MATCOMPOSITE 97203049c21SJunchao Zhang 97303049c21SJunchao Zhang @*/ 97403049c21SJunchao Zhang PetscErrorCode MatCompositeSetScalings(Mat mat,const PetscScalar *scalings) 97503049c21SJunchao Zhang { 97603049c21SJunchao Zhang PetscErrorCode ierr; 97703049c21SJunchao Zhang 97803049c21SJunchao Zhang PetscFunctionBegin; 97903049c21SJunchao Zhang PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 98003049c21SJunchao Zhang PetscValidPointer(scalings,2); 98103049c21SJunchao Zhang PetscValidLogicalCollectiveScalar(mat,*scalings,2); 98203049c21SJunchao Zhang ierr = PetscUseMethod(mat,"MatCompositeSetScalings_C",(Mat,const PetscScalar*),(mat,scalings));CHKERRQ(ierr); 98303049c21SJunchao Zhang PetscFunctionReturn(0); 98403049c21SJunchao Zhang } 98503049c21SJunchao Zhang 986f4259b30SLisandro Dalcin static struct _MatOps MatOps_Values = {NULL, 987f4259b30SLisandro Dalcin NULL, 988f4259b30SLisandro Dalcin NULL, 98941cd0125SJakub Kruzik MatMult_Composite, 9907bf3a71bSJakub Kruzik MatMultAdd_Composite, 99141cd0125SJakub Kruzik /* 5*/ MatMultTranspose_Composite, 9927bf3a71bSJakub Kruzik MatMultTransposeAdd_Composite, 993f4259b30SLisandro Dalcin NULL, 994f4259b30SLisandro Dalcin NULL, 995f4259b30SLisandro Dalcin NULL, 996f4259b30SLisandro Dalcin /* 10*/ NULL, 997f4259b30SLisandro Dalcin NULL, 998f4259b30SLisandro Dalcin NULL, 999f4259b30SLisandro Dalcin NULL, 1000f4259b30SLisandro Dalcin NULL, 1001f4259b30SLisandro Dalcin /* 15*/ NULL, 1002f4259b30SLisandro Dalcin NULL, 100341cd0125SJakub Kruzik MatGetDiagonal_Composite, 100441cd0125SJakub Kruzik MatDiagonalScale_Composite, 1005f4259b30SLisandro Dalcin NULL, 1006f4259b30SLisandro Dalcin /* 20*/ NULL, 100741cd0125SJakub Kruzik MatAssemblyEnd_Composite, 1008f4259b30SLisandro Dalcin NULL, 1009f4259b30SLisandro Dalcin NULL, 1010f4259b30SLisandro Dalcin /* 24*/ NULL, 1011f4259b30SLisandro Dalcin NULL, 1012f4259b30SLisandro Dalcin NULL, 1013f4259b30SLisandro Dalcin NULL, 1014f4259b30SLisandro Dalcin NULL, 1015f4259b30SLisandro Dalcin /* 29*/ NULL, 1016f4259b30SLisandro Dalcin NULL, 1017f4259b30SLisandro Dalcin NULL, 1018f4259b30SLisandro Dalcin NULL, 1019f4259b30SLisandro Dalcin NULL, 1020f4259b30SLisandro Dalcin /* 34*/ NULL, 1021f4259b30SLisandro Dalcin NULL, 1022f4259b30SLisandro Dalcin NULL, 1023f4259b30SLisandro Dalcin NULL, 1024f4259b30SLisandro Dalcin NULL, 1025f4259b30SLisandro Dalcin /* 39*/ NULL, 1026f4259b30SLisandro Dalcin NULL, 1027f4259b30SLisandro Dalcin NULL, 1028f4259b30SLisandro Dalcin NULL, 1029f4259b30SLisandro Dalcin NULL, 1030f4259b30SLisandro Dalcin /* 44*/ NULL, 103141cd0125SJakub Kruzik MatScale_Composite, 103241cd0125SJakub Kruzik MatShift_Basic, 1033f4259b30SLisandro Dalcin NULL, 1034f4259b30SLisandro Dalcin NULL, 1035f4259b30SLisandro Dalcin /* 49*/ NULL, 1036f4259b30SLisandro Dalcin NULL, 1037f4259b30SLisandro Dalcin NULL, 1038f4259b30SLisandro Dalcin NULL, 1039f4259b30SLisandro Dalcin NULL, 1040f4259b30SLisandro Dalcin /* 54*/ NULL, 1041f4259b30SLisandro Dalcin NULL, 1042f4259b30SLisandro Dalcin NULL, 1043f4259b30SLisandro Dalcin NULL, 1044f4259b30SLisandro Dalcin NULL, 1045f4259b30SLisandro Dalcin /* 59*/ NULL, 104641cd0125SJakub Kruzik MatDestroy_Composite, 1047f4259b30SLisandro Dalcin NULL, 1048f4259b30SLisandro Dalcin NULL, 1049f4259b30SLisandro Dalcin NULL, 1050f4259b30SLisandro Dalcin /* 64*/ NULL, 1051f4259b30SLisandro Dalcin NULL, 1052f4259b30SLisandro Dalcin NULL, 1053f4259b30SLisandro Dalcin NULL, 1054f4259b30SLisandro Dalcin NULL, 1055f4259b30SLisandro Dalcin /* 69*/ NULL, 1056f4259b30SLisandro Dalcin NULL, 1057f4259b30SLisandro Dalcin NULL, 1058f4259b30SLisandro Dalcin NULL, 1059f4259b30SLisandro Dalcin NULL, 1060f4259b30SLisandro Dalcin /* 74*/ NULL, 1061f4259b30SLisandro Dalcin NULL, 10624b2558d6SJakub Kruzik MatSetFromOptions_Composite, 1063f4259b30SLisandro Dalcin NULL, 1064f4259b30SLisandro Dalcin NULL, 1065f4259b30SLisandro Dalcin /* 79*/ NULL, 1066f4259b30SLisandro Dalcin NULL, 1067f4259b30SLisandro Dalcin NULL, 1068f4259b30SLisandro Dalcin NULL, 1069f4259b30SLisandro Dalcin NULL, 1070f4259b30SLisandro Dalcin /* 84*/ NULL, 1071f4259b30SLisandro Dalcin NULL, 1072f4259b30SLisandro Dalcin NULL, 1073f4259b30SLisandro Dalcin NULL, 1074f4259b30SLisandro Dalcin NULL, 1075f4259b30SLisandro Dalcin /* 89*/ NULL, 1076f4259b30SLisandro Dalcin NULL, 1077f4259b30SLisandro Dalcin NULL, 1078f4259b30SLisandro Dalcin NULL, 1079f4259b30SLisandro Dalcin NULL, 1080f4259b30SLisandro Dalcin /* 94*/ NULL, 1081f4259b30SLisandro Dalcin NULL, 1082f4259b30SLisandro Dalcin NULL, 1083f4259b30SLisandro Dalcin NULL, 1084f4259b30SLisandro Dalcin NULL, 1085f4259b30SLisandro Dalcin /*99*/ NULL, 1086f4259b30SLisandro Dalcin NULL, 1087f4259b30SLisandro Dalcin NULL, 1088f4259b30SLisandro Dalcin NULL, 1089f4259b30SLisandro Dalcin NULL, 1090f4259b30SLisandro Dalcin /*104*/ NULL, 1091f4259b30SLisandro Dalcin NULL, 1092f4259b30SLisandro Dalcin NULL, 1093f4259b30SLisandro Dalcin NULL, 1094f4259b30SLisandro Dalcin NULL, 1095f4259b30SLisandro Dalcin /*109*/ NULL, 1096f4259b30SLisandro Dalcin NULL, 1097f4259b30SLisandro Dalcin NULL, 1098f4259b30SLisandro Dalcin NULL, 1099f4259b30SLisandro Dalcin NULL, 1100f4259b30SLisandro Dalcin /*114*/ NULL, 1101f4259b30SLisandro Dalcin NULL, 1102f4259b30SLisandro Dalcin NULL, 1103f4259b30SLisandro Dalcin NULL, 1104f4259b30SLisandro Dalcin NULL, 1105f4259b30SLisandro Dalcin /*119*/ NULL, 1106f4259b30SLisandro Dalcin NULL, 1107f4259b30SLisandro Dalcin NULL, 1108f4259b30SLisandro Dalcin NULL, 1109f4259b30SLisandro Dalcin NULL, 1110f4259b30SLisandro Dalcin /*124*/ NULL, 1111f4259b30SLisandro Dalcin NULL, 1112f4259b30SLisandro Dalcin NULL, 1113f4259b30SLisandro Dalcin NULL, 1114f4259b30SLisandro Dalcin NULL, 1115f4259b30SLisandro Dalcin /*129*/ NULL, 1116f4259b30SLisandro Dalcin NULL, 1117f4259b30SLisandro Dalcin NULL, 1118f4259b30SLisandro Dalcin NULL, 1119f4259b30SLisandro Dalcin NULL, 1120f4259b30SLisandro Dalcin /*134*/ NULL, 1121f4259b30SLisandro Dalcin NULL, 1122f4259b30SLisandro Dalcin NULL, 1123f4259b30SLisandro Dalcin NULL, 1124f4259b30SLisandro Dalcin NULL, 1125f4259b30SLisandro Dalcin /*139*/ NULL, 1126f4259b30SLisandro Dalcin NULL, 1127f4259b30SLisandro Dalcin NULL 112841cd0125SJakub Kruzik }; 112941cd0125SJakub Kruzik 113041cd0125SJakub Kruzik /*MC 113141cd0125SJakub Kruzik MATCOMPOSITE - A matrix defined by the sum (or product) of one or more matrices. 113241cd0125SJakub Kruzik The matrices need to have a correct size and parallel layout for the sum or product to be valid. 113341cd0125SJakub Kruzik 113441cd0125SJakub Kruzik Notes: 113541cd0125SJakub Kruzik to use the product of the matrices call MatCompositeSetType(mat,MAT_COMPOSITE_MULTIPLICATIVE); 113641cd0125SJakub Kruzik 113741cd0125SJakub Kruzik Level: advanced 113841cd0125SJakub Kruzik 113903049c21SJunchao Zhang .seealso: MatCreateComposite(), MatCompositeSetScalings(), MatCompositeAddMat(), MatSetType(), MatCompositeSetType(), MatCompositeGetType(), MatCompositeSetMatStructure(), MatCompositeGetMatStructure(), MatCompositeMerge(), MatCompositeSetMergeType(), MatCompositeGetNumberMat(), MatCompositeGetMat() 114041cd0125SJakub Kruzik M*/ 114141cd0125SJakub Kruzik 114241cd0125SJakub Kruzik PETSC_EXTERN PetscErrorCode MatCreate_Composite(Mat A) 114341cd0125SJakub Kruzik { 114441cd0125SJakub Kruzik Mat_Composite *b; 114541cd0125SJakub Kruzik PetscErrorCode ierr; 114641cd0125SJakub Kruzik 114741cd0125SJakub Kruzik PetscFunctionBegin; 114841cd0125SJakub Kruzik ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 114941cd0125SJakub Kruzik A->data = (void*)b; 115041cd0125SJakub Kruzik ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 115141cd0125SJakub Kruzik 115241cd0125SJakub Kruzik ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 115341cd0125SJakub Kruzik ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 115441cd0125SJakub Kruzik 115541cd0125SJakub Kruzik A->assembled = PETSC_TRUE; 115641cd0125SJakub Kruzik A->preallocated = PETSC_TRUE; 115741cd0125SJakub Kruzik b->type = MAT_COMPOSITE_ADDITIVE; 115841cd0125SJakub Kruzik b->scale = 1.0; 115941cd0125SJakub Kruzik b->nmat = 0; 11604b2558d6SJakub Kruzik b->merge = PETSC_FALSE; 11618c8613bfSJakub Kruzik b->mergetype = MAT_COMPOSITE_MERGE_RIGHT; 11623b35acafSJakub Kruzik b->structure = DIFFERENT_NONZERO_PATTERN; 116303049c21SJunchao Zhang b->merge_mvctx = PETSC_TRUE; 116403049c21SJunchao Zhang 116541cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeAddMat_C",MatCompositeAddMat_Composite);CHKERRQ(ierr); 116641cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetType_C",MatCompositeSetType_Composite);CHKERRQ(ierr); 11676dbc55e5SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetType_C",MatCompositeGetType_Composite);CHKERRQ(ierr); 11688c8613bfSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMergeType_C",MatCompositeSetMergeType_Composite);CHKERRQ(ierr); 11693b35acafSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetMatStructure_C",MatCompositeSetMatStructure_Composite);CHKERRQ(ierr); 11703b35acafSJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMatStructure_C",MatCompositeGetMatStructure_Composite);CHKERRQ(ierr); 117141cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeMerge_C",MatCompositeMerge_Composite);CHKERRQ(ierr); 11726d0add67SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetNumberMat_C",MatCompositeGetNumberMat_Composite);CHKERRQ(ierr); 117341cd0125SJakub Kruzik ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeGetMat_C",MatCompositeGetMat_Composite);CHKERRQ(ierr); 117403049c21SJunchao Zhang ierr = PetscObjectComposeFunction((PetscObject)A,"MatCompositeSetScalings_C",MatCompositeSetScalings_Composite);CHKERRQ(ierr); 117541cd0125SJakub Kruzik 117641cd0125SJakub Kruzik ierr = PetscObjectChangeTypeName((PetscObject)A,MATCOMPOSITE);CHKERRQ(ierr); 117741cd0125SJakub Kruzik PetscFunctionReturn(0); 117841cd0125SJakub Kruzik } 117941cd0125SJakub Kruzik 1180