1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
2ceb9aaf7SBarry Smith
3d751fb92SStefano Zampini PETSC_EXTERN PetscErrorCode VecGetRootType_Private(Vec, VecType *);
4d751fb92SStefano Zampini
5ceb9aaf7SBarry Smith typedef struct {
6986c4d72SJose E. Roman Mat A; /* sparse matrix */
7986c4d72SJose E. Roman Mat U, V; /* dense tall-skinny matrices */
8986c4d72SJose E. Roman Vec c; /* sequential vector containing the diagonal of C */
9986c4d72SJose E. Roman Vec work1, work2; /* sequential vectors that hold partial products */
100575051bSJose E. Roman Vec xl, yl; /* auxiliary sequential vectors for matmult operation */
11ab92ecdeSBarry Smith } Mat_LRC;
12ab92ecdeSBarry Smith
MatMult_LRC_kernel(Mat N,Vec x,Vec y,PetscBool transpose)13d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_LRC_kernel(Mat N, Vec x, Vec y, PetscBool transpose)
14d71ae5a4SJacob Faibussowitsch {
15ab92ecdeSBarry Smith Mat_LRC *Na = (Mat_LRC *)N->data;
16d751fb92SStefano Zampini PetscMPIInt size;
17d751fb92SStefano Zampini Mat U, V;
18ceb9aaf7SBarry Smith
19ceb9aaf7SBarry Smith PetscFunctionBegin;
20d751fb92SStefano Zampini U = transpose ? Na->V : Na->U;
21d751fb92SStefano Zampini V = transpose ? Na->U : Na->V;
229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)N), &size));
23d751fb92SStefano Zampini if (size == 1) {
249566063dSJacob Faibussowitsch PetscCall(MatMultHermitianTranspose(V, x, Na->work1));
251baa6e33SBarry Smith if (Na->c) PetscCall(VecPointwiseMult(Na->work1, Na->c, Na->work1));
26d751fb92SStefano Zampini if (Na->A) {
27d751fb92SStefano Zampini if (transpose) {
289566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A, x, y));
29d751fb92SStefano Zampini } else {
309566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A, x, y));
31d751fb92SStefano Zampini }
329566063dSJacob Faibussowitsch PetscCall(MatMultAdd(U, Na->work1, y, y));
33d751fb92SStefano Zampini } else {
349566063dSJacob Faibussowitsch PetscCall(MatMult(U, Na->work1, y));
35d751fb92SStefano Zampini }
36d751fb92SStefano Zampini } else {
37d751fb92SStefano Zampini Mat Uloc, Vloc;
38d751fb92SStefano Zampini Vec yl, xl;
39d751fb92SStefano Zampini const PetscScalar *w1;
40d751fb92SStefano Zampini PetscScalar *w2;
41d751fb92SStefano Zampini PetscInt nwork;
42d751fb92SStefano Zampini
43d751fb92SStefano Zampini xl = transpose ? Na->yl : Na->xl;
44d751fb92SStefano Zampini yl = transpose ? Na->xl : Na->yl;
459566063dSJacob Faibussowitsch PetscCall(VecGetLocalVector(y, yl));
469566063dSJacob Faibussowitsch PetscCall(MatDenseGetLocalMatrix(U, &Uloc));
479566063dSJacob Faibussowitsch PetscCall(MatDenseGetLocalMatrix(V, &Vloc));
480575051bSJose E. Roman
49ab92ecdeSBarry Smith /* multiply the local part of V with the local part of x */
509566063dSJacob Faibussowitsch PetscCall(VecGetLocalVectorRead(x, xl));
519566063dSJacob Faibussowitsch PetscCall(MatMultHermitianTranspose(Vloc, xl, Na->work1));
529566063dSJacob Faibussowitsch PetscCall(VecRestoreLocalVectorRead(x, xl));
53ab92ecdeSBarry Smith
5486eed97dSJose E. Roman /* form the sum of all the local multiplies: this is work2 = V'*x =
55ab92ecdeSBarry Smith sum_{all processors} work1 */
569566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Na->work1, &w1));
579566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(Na->work2, &w2));
589566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(Na->work1, &nwork));
59*e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Allreduce(w1, w2, nwork, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject)N)));
609566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Na->work1, &w1));
619566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(Na->work2, &w2));
62ab92ecdeSBarry Smith
63986c4d72SJose E. Roman if (Na->c) { /* work2 = C*work2 */
649566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Na->work2, Na->c, Na->work2));
65986c4d72SJose E. Roman }
66986c4d72SJose E. Roman
6786eed97dSJose E. Roman if (Na->A) {
68d751fb92SStefano Zampini /* form y = A*x or A^t*x */
69d751fb92SStefano Zampini if (transpose) {
709566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A, x, y));
71d751fb92SStefano Zampini } else {
729566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A, x, y));
73d751fb92SStefano Zampini }
7486eed97dSJose E. Roman /* multiply-add y = y + U*work2 */
759566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Uloc, Na->work2, yl, yl));
7686eed97dSJose E. Roman } else {
7786eed97dSJose E. Roman /* multiply y = U*work2 */
789566063dSJacob Faibussowitsch PetscCall(MatMult(Uloc, Na->work2, yl));
7986eed97dSJose E. Roman }
800575051bSJose E. Roman
819566063dSJacob Faibussowitsch PetscCall(VecRestoreLocalVector(y, yl));
82d751fb92SStefano Zampini }
833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
84ceb9aaf7SBarry Smith }
85ceb9aaf7SBarry Smith
MatMult_LRC(Mat N,Vec x,Vec y)86d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_LRC(Mat N, Vec x, Vec y)
87d71ae5a4SJacob Faibussowitsch {
88d751fb92SStefano Zampini PetscFunctionBegin;
899566063dSJacob Faibussowitsch PetscCall(MatMult_LRC_kernel(N, x, y, PETSC_FALSE));
903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
91d751fb92SStefano Zampini }
92d751fb92SStefano Zampini
MatMultTranspose_LRC(Mat N,Vec x,Vec y)93d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_LRC(Mat N, Vec x, Vec y)
94d71ae5a4SJacob Faibussowitsch {
95d751fb92SStefano Zampini PetscFunctionBegin;
969566063dSJacob Faibussowitsch PetscCall(MatMult_LRC_kernel(N, x, y, PETSC_TRUE));
973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
98d751fb92SStefano Zampini }
99d751fb92SStefano Zampini
MatDestroy_LRC(Mat N)100d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_LRC(Mat N)
101d71ae5a4SJacob Faibussowitsch {
102ab92ecdeSBarry Smith Mat_LRC *Na = (Mat_LRC *)N->data;
103ceb9aaf7SBarry Smith
104ceb9aaf7SBarry Smith PetscFunctionBegin;
1059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->A));
1069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->U));
1079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->V));
1089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->c));
1099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->work1));
1109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->work2));
1119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->xl));
1129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->yl));
1139566063dSJacob Faibussowitsch PetscCall(PetscFree(N->data));
1149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatLRCGetMats_C", NULL));
115bcf2175cSMatthew Knepley PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatLRCSetMats_C", NULL));
1163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
117267ca84cSJose E. Roman }
118267ca84cSJose E. Roman
MatLRCGetMats_LRC(Mat N,Mat * A,Mat * U,Vec * c,Mat * V)119d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLRCGetMats_LRC(Mat N, Mat *A, Mat *U, Vec *c, Mat *V)
120d71ae5a4SJacob Faibussowitsch {
121267ca84cSJose E. Roman Mat_LRC *Na = (Mat_LRC *)N->data;
122267ca84cSJose E. Roman
123267ca84cSJose E. Roman PetscFunctionBegin;
124267ca84cSJose E. Roman if (A) *A = Na->A;
125267ca84cSJose E. Roman if (U) *U = Na->U;
126267ca84cSJose E. Roman if (c) *c = Na->c;
127267ca84cSJose E. Roman if (V) *V = Na->V;
1283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
129267ca84cSJose E. Roman }
130267ca84cSJose E. Roman
MatLRCSetMats_LRC(Mat N,Mat A,Mat U,Vec c,Mat V)131bcf2175cSMatthew Knepley static PetscErrorCode MatLRCSetMats_LRC(Mat N, Mat A, Mat U, Vec c, Mat V)
132bcf2175cSMatthew Knepley {
133bcf2175cSMatthew Knepley Mat_LRC *Na = (Mat_LRC *)N->data;
134bcf2175cSMatthew Knepley
135bcf2175cSMatthew Knepley PetscFunctionBegin;
136bcf2175cSMatthew Knepley PetscCall(PetscObjectReference((PetscObject)A));
137bcf2175cSMatthew Knepley PetscCall(PetscObjectReference((PetscObject)U));
138bcf2175cSMatthew Knepley PetscCall(PetscObjectReference((PetscObject)V));
139bcf2175cSMatthew Knepley PetscCall(PetscObjectReference((PetscObject)c));
140bcf2175cSMatthew Knepley PetscCall(MatDestroy(&Na->A));
141bcf2175cSMatthew Knepley PetscCall(MatDestroy(&Na->U));
142bcf2175cSMatthew Knepley PetscCall(MatDestroy(&Na->V));
143bcf2175cSMatthew Knepley PetscCall(VecDestroy(&Na->c));
144bcf2175cSMatthew Knepley Na->A = A;
145bcf2175cSMatthew Knepley Na->U = U;
146bcf2175cSMatthew Knepley Na->c = c;
147bcf2175cSMatthew Knepley Na->V = V;
148bcf2175cSMatthew Knepley PetscFunctionReturn(PETSC_SUCCESS);
149bcf2175cSMatthew Knepley }
150bcf2175cSMatthew Knepley
151267ca84cSJose E. Roman /*@
152267ca84cSJose E. Roman MatLRCGetMats - Returns the constituents of an LRC matrix
153267ca84cSJose E. Roman
154bcf2175cSMatthew Knepley Not collective
155267ca84cSJose E. Roman
156267ca84cSJose E. Roman Input Parameter:
15711a5261eSBarry Smith . N - matrix of type `MATLRC`
158267ca84cSJose E. Roman
159267ca84cSJose E. Roman Output Parameters:
160267ca84cSJose E. Roman + A - the (sparse) matrix
1616b867d5aSJose E. Roman . U - first dense rectangular (tall and skinny) matrix
1626b867d5aSJose E. Roman . c - a sequential vector containing the diagonal of C
1636b867d5aSJose E. Roman - V - second dense rectangular (tall and skinny) matrix
164267ca84cSJose E. Roman
165267ca84cSJose E. Roman Level: intermediate
166267ca84cSJose E. Roman
1672ef1f0ffSBarry Smith Notes:
168bcf2175cSMatthew Knepley The returned matrices should not be destroyed by the caller.
1692ef1f0ffSBarry Smith
1702ef1f0ffSBarry Smith `U`, `c`, `V` may be `NULL` if not needed
1712ef1f0ffSBarry Smith
172bcf2175cSMatthew Knepley .seealso: [](ch_matrices), `MatLRCSetMats()`, `Mat`, `MATLRC`, `MatCreateLRC()`
173267ca84cSJose E. Roman @*/
MatLRCGetMats(Mat N,Mat * A,Mat * U,Vec * c,Mat * V)174d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLRCGetMats(Mat N, Mat *A, Mat *U, Vec *c, Mat *V)
175d71ae5a4SJacob Faibussowitsch {
176267ca84cSJose E. Roman PetscFunctionBegin;
177cac4c232SBarry Smith PetscUseMethod(N, "MatLRCGetMats_C", (Mat, Mat *, Mat *, Vec *, Mat *), (N, A, U, c, V));
1783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
179ceb9aaf7SBarry Smith }
180ceb9aaf7SBarry Smith
181bcf2175cSMatthew Knepley /*@
182bcf2175cSMatthew Knepley MatLRCSetMats - Sets the constituents of an LRC matrix
183bcf2175cSMatthew Knepley
184bcf2175cSMatthew Knepley Logically collective
185bcf2175cSMatthew Knepley
186bcf2175cSMatthew Knepley Input Parameters:
187bcf2175cSMatthew Knepley + N - matrix of type `MATLRC`
188bcf2175cSMatthew Knepley . A - the (sparse) matrix
189bcf2175cSMatthew Knepley . U - first dense rectangular (tall and skinny) matrix
190bcf2175cSMatthew Knepley . c - a sequential vector containing the diagonal of C
191bcf2175cSMatthew Knepley - V - second dense rectangular (tall and skinny) matrix
192bcf2175cSMatthew Knepley
193bcf2175cSMatthew Knepley Level: intermediate
194bcf2175cSMatthew Knepley
195bcf2175cSMatthew Knepley Note:
196bcf2175cSMatthew Knepley If `V` is `NULL`, then it is assumed to be identical to `U`.
197bcf2175cSMatthew Knepley
198bcf2175cSMatthew Knepley .seealso: [](ch_matrices), `MatLRCGetMats()`, `Mat`, `MATLRC`, `MatCreateLRC()`
199bcf2175cSMatthew Knepley @*/
MatLRCSetMats(Mat N,Mat A,Mat U,Vec c,Mat V)200bcf2175cSMatthew Knepley PetscErrorCode MatLRCSetMats(Mat N, Mat A, Mat U, Vec c, Mat V)
201bcf2175cSMatthew Knepley {
202bcf2175cSMatthew Knepley PetscInt k, k1, m, n, m1, n1;
203bcf2175cSMatthew Knepley PetscBool match;
204bcf2175cSMatthew Knepley
205bcf2175cSMatthew Knepley PetscFunctionBegin;
2060d6f747bSJacob Faibussowitsch if (A) PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
2070d6f747bSJacob Faibussowitsch PetscValidHeaderSpecific(U, MAT_CLASSID, 3);
2080d6f747bSJacob Faibussowitsch if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 4);
209bcf2175cSMatthew Knepley if (V) {
2100d6f747bSJacob Faibussowitsch PetscValidHeaderSpecific(V, MAT_CLASSID, 5);
2110d6f747bSJacob Faibussowitsch PetscCheckSameComm(U, 3, V, 5);
212bcf2175cSMatthew Knepley }
2130d6f747bSJacob Faibussowitsch if (A) PetscCheckSameComm(A, 2, U, 3);
214bcf2175cSMatthew Knepley if (!V) V = U;
215bcf2175cSMatthew Knepley PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)U, &match, MATSEQDENSE, MATMPIDENSE, ""));
216bcf2175cSMatthew Knepley PetscCheck(match, PetscObjectComm((PetscObject)U), PETSC_ERR_SUP, "Matrix U must be of type dense, found %s", ((PetscObject)U)->type_name);
217bcf2175cSMatthew Knepley PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)V, &match, MATSEQDENSE, MATMPIDENSE, ""));
218bcf2175cSMatthew Knepley PetscCheck(match, PetscObjectComm((PetscObject)U), PETSC_ERR_SUP, "Matrix V must be of type dense, found %s", ((PetscObject)V)->type_name);
219bcf2175cSMatthew Knepley PetscCall(PetscStrcmp(U->defaultvectype, V->defaultvectype, &match));
220bcf2175cSMatthew Knepley PetscCheck(match, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_WRONG, "Matrix U and V must have the same VecType %s != %s", U->defaultvectype, V->defaultvectype);
221bcf2175cSMatthew Knepley if (A) {
222bcf2175cSMatthew Knepley PetscCall(PetscStrcmp(A->defaultvectype, U->defaultvectype, &match));
223bcf2175cSMatthew Knepley PetscCheck(match, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_WRONG, "Matrix A and U must have the same VecType %s != %s", A->defaultvectype, U->defaultvectype);
224bcf2175cSMatthew Knepley }
225bcf2175cSMatthew Knepley PetscCall(MatGetSize(U, NULL, &k));
226bcf2175cSMatthew Knepley PetscCall(MatGetSize(V, NULL, &k1));
227bcf2175cSMatthew Knepley PetscCheck(k == k1, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_INCOMP, "U and V have different number of columns (%" PetscInt_FMT " vs %" PetscInt_FMT ")", k, k1);
228bcf2175cSMatthew Knepley PetscCall(MatGetLocalSize(U, &m, NULL));
229bcf2175cSMatthew Knepley PetscCall(MatGetLocalSize(V, &n, NULL));
230bcf2175cSMatthew Knepley if (A) {
231bcf2175cSMatthew Knepley PetscCall(MatGetLocalSize(A, &m1, &n1));
232bcf2175cSMatthew Knepley PetscCheck(m == m1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local dimensions of U %" PetscInt_FMT " and A %" PetscInt_FMT " do not match", m, m1);
233bcf2175cSMatthew Knepley PetscCheck(n == n1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local dimensions of V %" PetscInt_FMT " and A %" PetscInt_FMT " do not match", n, n1);
234bcf2175cSMatthew Knepley }
235bcf2175cSMatthew Knepley if (c) {
236bcf2175cSMatthew Knepley PetscMPIInt size, csize;
237bcf2175cSMatthew Knepley
238bcf2175cSMatthew Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)U), &size));
239bcf2175cSMatthew Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)c), &csize));
240bcf2175cSMatthew Knepley PetscCall(VecGetSize(c, &k1));
241bcf2175cSMatthew Knepley PetscCheck(k == k1, PetscObjectComm((PetscObject)c), PETSC_ERR_ARG_INCOMP, "The length of c %" PetscInt_FMT " does not match the number of columns of U and V (%" PetscInt_FMT ")", k1, k);
242bcf2175cSMatthew Knepley PetscCheck(csize == 1 || csize == size, PetscObjectComm((PetscObject)c), PETSC_ERR_ARG_INCOMP, "U and c must have the same communicator size %d != %d", size, csize);
243bcf2175cSMatthew Knepley }
244bcf2175cSMatthew Knepley PetscCall(MatSetSizes(N, m, n, PETSC_DECIDE, PETSC_DECIDE));
245bcf2175cSMatthew Knepley
246bcf2175cSMatthew Knepley PetscUseMethod(N, "MatLRCSetMats_C", (Mat, Mat, Mat, Vec, Mat), (N, A, U, c, V));
247bcf2175cSMatthew Knepley PetscFunctionReturn(PETSC_SUCCESS);
248bcf2175cSMatthew Knepley }
249bcf2175cSMatthew Knepley
MatSetUp_LRC(Mat N)250bcf2175cSMatthew Knepley static PetscErrorCode MatSetUp_LRC(Mat N)
251bcf2175cSMatthew Knepley {
252bcf2175cSMatthew Knepley Mat_LRC *Na = (Mat_LRC *)N->data;
253bcf2175cSMatthew Knepley Mat A = Na->A;
254bcf2175cSMatthew Knepley Mat U = Na->U;
255bcf2175cSMatthew Knepley Mat V = Na->V;
256bcf2175cSMatthew Knepley Vec c = Na->c;
257bcf2175cSMatthew Knepley Mat Uloc;
258bcf2175cSMatthew Knepley PetscMPIInt size, csize = 0;
259d070fe2eSStefano Zampini PetscBool sym = (PetscBool)(U == V), dummy;
260bcf2175cSMatthew Knepley
261bcf2175cSMatthew Knepley PetscFunctionBegin;
262bcf2175cSMatthew Knepley PetscCall(MatSetVecType(N, U->defaultvectype));
263bcf2175cSMatthew Knepley // Flag matrix as symmetric if A is symmetric and U == V
264d070fe2eSStefano Zampini if (A && sym) PetscCall(MatIsSymmetricKnown(A, &dummy, &sym));
265d070fe2eSStefano Zampini PetscCall(MatSetOption(N, MAT_SYMMETRIC, sym));
266bcf2175cSMatthew Knepley PetscCall(MatDenseGetLocalMatrix(Na->U, &Uloc));
267bcf2175cSMatthew Knepley PetscCall(MatCreateVecs(Uloc, &Na->work1, NULL));
268bcf2175cSMatthew Knepley
269bcf2175cSMatthew Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)U), &size));
270bcf2175cSMatthew Knepley if (c) PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)c), &csize));
271bcf2175cSMatthew Knepley if (size != 1) {
272bcf2175cSMatthew Knepley Mat Vloc;
273bcf2175cSMatthew Knepley
274bcf2175cSMatthew Knepley if (Na->c && csize != 1) { /* scatter parallel vector to sequential */
275bcf2175cSMatthew Knepley VecScatter sct;
276bcf2175cSMatthew Knepley
277bcf2175cSMatthew Knepley PetscCall(VecScatterCreateToAll(Na->c, &sct, &c));
278bcf2175cSMatthew Knepley PetscCall(VecScatterBegin(sct, Na->c, c, INSERT_VALUES, SCATTER_FORWARD));
279bcf2175cSMatthew Knepley PetscCall(VecScatterEnd(sct, Na->c, c, INSERT_VALUES, SCATTER_FORWARD));
280bcf2175cSMatthew Knepley PetscCall(VecScatterDestroy(&sct));
281bcf2175cSMatthew Knepley PetscCall(VecDestroy(&Na->c));
282bcf2175cSMatthew Knepley Na->c = c;
283bcf2175cSMatthew Knepley }
284bcf2175cSMatthew Knepley PetscCall(MatDenseGetLocalMatrix(Na->V, &Vloc));
285bcf2175cSMatthew Knepley PetscCall(VecDuplicate(Na->work1, &Na->work2));
286bcf2175cSMatthew Knepley PetscCall(MatCreateVecs(Vloc, NULL, &Na->xl));
287bcf2175cSMatthew Knepley PetscCall(MatCreateVecs(Uloc, NULL, &Na->yl));
288bcf2175cSMatthew Knepley }
289bcf2175cSMatthew Knepley // Internally create a scaling vector if roottypes do not match
290bcf2175cSMatthew Knepley if (Na->c) {
291bcf2175cSMatthew Knepley VecType rt1, rt2;
292bcf2175cSMatthew Knepley PetscBool match;
293bcf2175cSMatthew Knepley
294bcf2175cSMatthew Knepley PetscCall(VecGetRootType_Private(Na->work1, &rt1));
295bcf2175cSMatthew Knepley PetscCall(VecGetRootType_Private(Na->c, &rt2));
296bcf2175cSMatthew Knepley PetscCall(PetscStrcmp(rt1, rt2, &match));
297bcf2175cSMatthew Knepley if (!match) {
298bcf2175cSMatthew Knepley PetscCall(VecDuplicate(Na->c, &c));
299bcf2175cSMatthew Knepley PetscCall(VecCopy(Na->c, c));
300bcf2175cSMatthew Knepley PetscCall(VecDestroy(&Na->c));
301bcf2175cSMatthew Knepley Na->c = c;
302bcf2175cSMatthew Knepley }
303bcf2175cSMatthew Knepley }
304bcf2175cSMatthew Knepley N->assembled = PETSC_TRUE;
305bcf2175cSMatthew Knepley N->preallocated = PETSC_TRUE;
306bcf2175cSMatthew Knepley PetscFunctionReturn(PETSC_SUCCESS);
307bcf2175cSMatthew Knepley }
308bcf2175cSMatthew Knepley
MatCreate_LRC(Mat N)309bcf2175cSMatthew Knepley PETSC_EXTERN PetscErrorCode MatCreate_LRC(Mat N)
310bcf2175cSMatthew Knepley {
311bcf2175cSMatthew Knepley Mat_LRC *Na;
312bcf2175cSMatthew Knepley
313bcf2175cSMatthew Knepley PetscFunctionBegin;
314bcf2175cSMatthew Knepley PetscCall(PetscObjectChangeTypeName((PetscObject)N, MATLRC));
315bcf2175cSMatthew Knepley PetscCall(PetscNew(&Na));
316bcf2175cSMatthew Knepley N->data = (void *)Na;
317bcf2175cSMatthew Knepley N->ops->destroy = MatDestroy_LRC;
318bcf2175cSMatthew Knepley N->ops->setup = MatSetUp_LRC;
319bcf2175cSMatthew Knepley N->ops->mult = MatMult_LRC;
320bcf2175cSMatthew Knepley N->ops->multtranspose = MatMultTranspose_LRC;
321bcf2175cSMatthew Knepley
322bcf2175cSMatthew Knepley PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatLRCGetMats_C", MatLRCGetMats_LRC));
323bcf2175cSMatthew Knepley PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatLRCSetMats_C", MatLRCSetMats_LRC));
324bcf2175cSMatthew Knepley PetscFunctionReturn(PETSC_SUCCESS);
325bcf2175cSMatthew Knepley }
326bcf2175cSMatthew Knepley
32711a5261eSBarry Smith /*MC
32811a5261eSBarry Smith MATLRC - "lrc" - a matrix object that behaves like A + U*C*V'
329ceb9aaf7SBarry Smith
33011a5261eSBarry Smith Note:
33111a5261eSBarry Smith The matrix A + U*C*V' is not formed! Rather the matrix object performs the matrix-vector product `MatMult()`, by first multiplying by
33211a5261eSBarry Smith A and then adding the other term.
33311a5261eSBarry Smith
33411a5261eSBarry Smith Level: advanced
33511a5261eSBarry Smith
336bcf2175cSMatthew Knepley .seealso: [](ch_matrices), `Mat`, `MatCreateLRC()`, `MatMult()`, `MatLRCGetMats()`, `MatLRCSetMats()`
33711a5261eSBarry Smith M*/
33811a5261eSBarry Smith
33911a5261eSBarry Smith /*@
34011a5261eSBarry Smith MatCreateLRC - Creates a new matrix object that behaves like A + U*C*V' of type `MATLRC`
34111a5261eSBarry Smith
342c3339decSBarry Smith Collective
343ceb9aaf7SBarry Smith
3449d9032efSJose E. Roman Input Parameters:
3452ef1f0ffSBarry Smith + A - the (sparse) matrix (can be `NULL`)
3462ef1f0ffSBarry Smith . U - dense rectangular (tall and skinny) matrix
3472ef1f0ffSBarry Smith . V - dense rectangular (tall and skinny) matrix
3482ef1f0ffSBarry Smith - c - a vector containing the diagonal of C (can be `NULL`)
349ceb9aaf7SBarry Smith
350ceb9aaf7SBarry Smith Output Parameter:
351986c4d72SJose E. Roman . N - the matrix that represents A + U*C*V'
352ceb9aaf7SBarry Smith
3532ef1f0ffSBarry Smith Level: intermediate
3542ef1f0ffSBarry Smith
3559d9032efSJose E. Roman Notes:
356986c4d72SJose E. Roman The matrix A + U*C*V' is not formed! Rather the new matrix
35711a5261eSBarry Smith object performs the matrix-vector product `MatMult()`, by first multiplying by
3589d9032efSJose E. Roman A and then adding the other term.
3599d9032efSJose E. Roman
3602ef1f0ffSBarry Smith `C` is a diagonal matrix (represented as a vector) of order k,
3612ef1f0ffSBarry Smith where k is the number of columns of both `U` and `V`.
36286eed97dSJose E. Roman
3632ef1f0ffSBarry Smith If `A` is `NULL` then the new object behaves like a low-rank matrix U*C*V'.
364986c4d72SJose E. Roman
3652ef1f0ffSBarry Smith Use `V`=`U` (or `V`=`NULL`) for a symmetric low-rank correction, A + U*C*U'.
366986c4d72SJose E. Roman
3672ef1f0ffSBarry Smith If `c` is `NULL` then the low-rank correction is just U*V'.
3682ef1f0ffSBarry Smith If a sequential `c` vector is used for a parallel matrix,
369d751fb92SStefano Zampini PETSc assumes that the values of the vector are consistently set across processors.
37086eed97dSJose E. Roman
3711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATLRC`, `MatLRCGetMats()`
372ceb9aaf7SBarry Smith @*/
MatCreateLRC(Mat A,Mat U,Vec c,Mat V,Mat * N)373d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateLRC(Mat A, Mat U, Vec c, Mat V, Mat *N)
374d71ae5a4SJacob Faibussowitsch {
375ceb9aaf7SBarry Smith PetscFunctionBegin;
3769566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)U), N));
377bcf2175cSMatthew Knepley PetscCall(MatSetType(*N, MATLRC));
378bcf2175cSMatthew Knepley PetscCall(MatLRCSetMats(*N, A, U, c, V));
3799566063dSJacob Faibussowitsch PetscCall(MatSetUp(*N));
3803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
381ceb9aaf7SBarry Smith }
382