19 #include "AMGOperator.h"
23 int nLevel,
int smoother,
int param,
24 int coarseSolver,
int cycle,
34 leftProjection(false),
35 rightProjection(false),
45 preProcess((numDofs == 1) ? 1 : 50);
50 for (
int j = 0; j < AMG_NLevels; ++j)
51 ML_Gen_Smoother_MLS(ml_handle, j, ML_BOTH, 30., param);
54 int nBlocks, *blockIndices;
55 for (
int j = 0; j < AMG_NLevels; ++j) {
56 ML_Gen_Blocks_Aggregates(ml_agg, j, &nBlocks, &blockIndices);
57 ML_Gen_Smoother_BlockDiagScaledCheby(ml_handle, j, ML_BOTH, 30., param,
58 nBlocks, blockIndices);
68 ML_Gen_Smoother_SymGaussSeidel(ml_handle, ML_ALL_LEVELS, ML_BOTH, param, ML_DEFAULT);
70 ML_Gen_Smoother_BlockGaussSeidel(ml_handle, ML_ALL_LEVELS, ML_BOTH, param, ML_DEFAULT,
78 ML_Gen_Smoother_Jacobi(ml_handle, ML_ALL_LEVELS, ML_BOTH, param, ML_DEFAULT);
80 int size = ml_handle->Amat[0].getrow->Nrows;
81 int *blockIndices =
new int[size];
83 for (j = 0; j < size; ++j)
84 blockIndices[j] = j/numDofs;
85 for (j = 0; j < AMG_NLevels; ++j) {
86 size = ml_handle->Amat[j].getrow->Nrows;
87 ML_Gen_Smoother_VBlockJacobi(ml_handle, j, ML_BOTH, param, ML_DEFAULT,
88 size/numDofs, blockIndices);
90 delete[] blockIndices;
94 setCoarseSolver_Cycle(coarseSolver, cycle);
100 int nLevel,
int smoother,
int *param,
101 int coarseSolver,
int cycle,
111 leftProjection(false),
112 rightProjection(false),
122 preProcess((numDofs == 1) ? 1 : 50);
127 for (
int j = 0; j < AMG_NLevels; ++j)
128 ML_Gen_Smoother_MLS(ml_handle, j, ML_BOTH, 30., (param) ? param[j] : 2);
131 int nBlocks, *blockIndices;
132 for (
int j = 0; j < AMG_NLevels; ++j) {
133 ML_Gen_Blocks_Aggregates(ml_agg, j, &nBlocks, &blockIndices);
134 ML_Gen_Smoother_BlockDiagScaledCheby(ml_handle, j, ML_BOTH, 30., (param) ? param[j] : 2,
135 nBlocks, blockIndices);
145 for (
int j = 0; j < AMG_NLevels; ++j) {
146 ML_Gen_Smoother_SymGaussSeidel(ml_handle, j, ML_BOTH, (param) ? param[j] : 1, ML_DEFAULT);
150 for (
int j = 0; j < AMG_NLevels; ++j) {
151 ML_Gen_Smoother_BlockGaussSeidel(ml_handle, j, ML_BOTH, (param) ? param[j] : 1,
152 ML_DEFAULT, numDofs);
161 for (
int j = 0; j < AMG_NLevels; ++j) {
162 ML_Gen_Smoother_Jacobi(ml_handle, j, ML_BOTH, (param) ? param[j] : 1, ML_DEFAULT);
166 int size = ml_handle->Amat[0].getrow->Nrows;
167 int *blockIndices =
new int[size];
169 for (j = 0; j < size; ++j)
170 blockIndices[j] = j/numDofs;
171 for (j = 0; j < AMG_NLevels; ++j) {
172 size = ml_handle->Amat[j].getrow->Nrows;
173 ML_Gen_Smoother_VBlockJacobi(ml_handle, j, ML_BOTH, (param) ? param[j] : 1,
174 ML_DEFAULT, size/numDofs, blockIndices);
176 delete[] blockIndices;
180 setCoarseSolver_Cycle(coarseSolver, cycle);
185 void AMGOperator::preProcess(
int maxCoarseSize) {
190 if (MyComm.MyPID() == 0) {
192 cerr <<
" !!! For AMG preconditioner, the matrix must be 'Epetra_RowMatrix' object !!!\n";
199 ML_Set_PrintLevel(verbose);
200 ML_Create(&ml_handle, AMG_NLevels);
202 EpetraMatrix2MLMatrix(ml_handle, 0, Krow);
204 ML_Aggregate_Create(&ml_agg);
205 ML_Aggregate_Set_MaxCoarseSize(ml_agg, maxCoarseSize);
206 ML_Aggregate_Set_Threshold(ml_agg, 0.0);
209 if ((Q == 0) || (numDofs == 1)) {
210 ML_Aggregate_Set_CoarsenScheme_Uncoupled(ml_agg);
218 ML_Aggregate_Set_DampingFactor(ml_agg, 1.3333);
219 ML_Aggregate_Set_CoarsenScheme_MIS(ml_agg);
226 ML_Aggregate_Set_NullSpace(ml_agg, numDofs, Q->NumVectors(), Q->Values(), Q->MyLength());
227 QtQ =
new double[Q->NumVectors()*Q->NumVectors()];
228 double *work =
new double[Q->NumVectors()*Q->NumVectors()];
229 callBLAS.GEMM(
'T',
'N', Q->NumVectors(), Q->NumVectors(), Q->MyLength(),
230 1.0, Q->Values(), Q->MyLength(), Q->Values(), Q->MyLength(),
231 0.0, work, Q->NumVectors());
232 MyComm.SumAll(work, QtQ, Q->NumVectors()*Q->NumVectors());
235 callLAPACK.POTRF(
'U', Q->NumVectors(), QtQ, Q->NumVectors(), &info);
238 cerr <<
" !!! In AMG preconditioner, the null space vectors are linearly dependent !!!\n";
245 AMG_NLevels = ML_Gen_MGHierarchy_UsingAggregation(ml_handle, 0, ML_INCREASING, ml_agg);
250 void AMGOperator::setCoarseSolver_Cycle(
int coarseSolver,
int cycle) {
253 if (coarseSolver > -1) {
254 switch (coarseSolver) {
257 ML_Gen_CoarseSolverSuperLU(ml_handle, AMG_NLevels-1);
261 int options[AZ_OPTIONS_SIZE];
262 double params[AZ_PARAMS_SIZE];
263 int *proc_config =
new int[AZ_PROC_SIZE];
264 double *status =
new double[AZ_STATUS_SIZE];
265 AZ_defaults(options, params);
266 options[AZ_solver] = AZ_cg;
267 options[AZ_precond] = AZ_user_precond;
268 options[AZ_scaling] = AZ_none;
269 options[AZ_output] = 1;
273 options[AZ_output] = AZ_none;
275 AZ_set_proc_config(proc_config, get_global_comm());
277 params[AZ_tol] = 1.0e-14;
278 coarseLocalSize = ml_handle->Amat[AMG_NLevels-1].invec_leng;
279 MyComm.SumAll(&coarseLocalSize, &coarseGlobalSize, 1);
280 if ((verbose > 0) && (MyComm.MyPID() == 0))
281 cout <<
"\n --> Total number of coarse grid unknowns = " << coarseGlobalSize << endl;
284 int zCol = ml_agg->nullspace_dim;
285 double *ZZ = ml_agg->nullspace_vect;
286 ZcoarseTZcoarse =
new double[zCol*zCol];
287 double *tmp =
new double[zCol*zCol];
289 callBLAS.GEMM(
'T',
'N', zCol, zCol, coarseLocalSize, 1.0, ZZ, coarseLocalSize,
290 ZZ, coarseLocalSize, 0.0, tmp, zCol);
291 MyComm.SumAll(tmp, ZcoarseTZcoarse, zCol*zCol);
292 callLAPACK.POTRF(
'U', zCol, ZcoarseTZcoarse, zCol, &info);
295 cerr <<
" !!! In AMG preconditioner, for the coarse level, ";
296 cerr <<
"the null space vectors are linearly dependent !!!\n";
300 singularCoarse::setNullSpace(ml_agg->nullspace_vect, coarseLocalSize,
301 ml_agg->nullspace_dim, ZcoarseTZcoarse, &MyComm);
305 options[AZ_max_iter] = coarseGlobalSize;
311 ML_Gen_SmootherAztec(ml_handle, AMG_NLevels-1, options, params, proc_config, status,
312 options[AZ_max_iter], ML_PRESMOOTHER, NULL);
314 ML_Gen_SmootherAztec(ml_handle, AMG_NLevels-1, options, params, proc_config, status,
315 options[AZ_max_iter], ML_PRESMOOTHER,
316 (Q) ? singularCoarse::projection : NULL);
326 ML_Gen_Solver(ml_handle, ML_MGV, 0, AMG_NLevels-1);
329 ML_Gen_Solver(ml_handle, ML_MGW, 0, AMG_NLevels-1);
333 Prec =
new ML_Epetra::MultiLevelOperator(ml_handle, MyComm, K->OperatorDomainMap(),
334 K->OperatorDomainMap());
345 AMGOperator::~AMGOperator() {
350 ML_Destroy(&ml_handle);
351 ML_Aggregate_Destroy(&ml_agg);
359 if (ZcoarseTZcoarse) {
360 delete[] ZcoarseTZcoarse;
363 singularCoarse::setNullSpace(0, 0, 0, 0, 0);
372 return K->Apply(X, Y);
379 int xcol = X.NumVectors();
381 if (Y.NumVectors() < xcol)
384 double *valX = (rightProjection ==
true) ?
new double[xcol*X.MyLength()] : X.Values();
388 if ((rightProjection ==
true) && (Q)) {
389 int qcol = Q->NumVectors();
390 double *work =
new double[2*qcol*xcol];
391 memcpy(X2.Values(), X.Values(), xcol*X.MyLength()*
sizeof(double));
392 callBLAS.GEMM(
'T',
'N', qcol, xcol, Q->MyLength(), 1.0, Q->Values(), Q->MyLength(),
393 X2.Values(), X2.MyLength(), 0.0, work + qcol*xcol, qcol);
394 MyComm.SumAll(work + qcol*xcol, work, qcol*xcol);
396 callLAPACK.POTRS(
'U', qcol, xcol, QtQ, qcol, work, qcol, &info);
397 callBLAS.GEMM(
'N',
'N', X2.MyLength(), xcol, qcol, -1.0, Q->Values(), Q->MyLength(),
398 work, qcol, 1.0, X2.Values(), X2.MyLength());
402 Prec->ApplyInverse(X2, Y);
404 if (rightProjection ==
true)
407 if ((leftProjection ==
true) && (Q)) {
408 int qcol = Q->NumVectors();
409 double *work =
new double[2*qcol*xcol];
410 callBLAS.GEMM(
'T',
'N', qcol, xcol, Q->MyLength(), 1.0, Q->Values(), Q->MyLength(),
411 Y.Values(), Y.MyLength(), 0.0, work + qcol*xcol, qcol);
412 MyComm.SumAll(work + qcol*xcol, work, qcol*xcol);
414 callLAPACK.POTRS(
'U', qcol, xcol, QtQ, qcol, work, qcol, &info);
415 callBLAS.GEMM(
'N',
'N', Y.MyLength(), xcol, qcol, -1.0, Q->Values(), Q->MyLength(),
416 work, qcol, 1.0, Y.Values(), Y.MyLength());