int Stokhos::MeanBasedPreconditioner:: ApplyInverse(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { int myBlockRows = epetraCijk->numMyRows(); if (!use_block_apply) { EpetraExt::BlockMultiVector sg_input(View, *base_map, Input); EpetraExt::BlockMultiVector sg_result(View, *base_map, Result); for (int i=0; i<myBlockRows; i++) { mean_prec->ApplyInverse(*(sg_input.GetBlock(i)), *(sg_result.GetBlock(i))); } } else { int m = Input.NumVectors(); Epetra_MultiVector input_block( View, *base_map, Input.Values(), base_map->NumMyElements(), m*myBlockRows); Epetra_MultiVector result_block( View, *base_map, Result.Values(), base_map->NumMyElements(), m*myBlockRows); mean_prec->ApplyInverse(input_block, result_block); } return 0; }
int Stokhos::MeanBasedPreconditioner:: Apply(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { int myBlockRows = epetraCijk->numMyRows(); EpetraExt::BlockMultiVector sg_input(View, *base_map, Input); EpetraExt::BlockMultiVector sg_result(View, *base_map, Result); for (int i=0; i<myBlockRows; i++) { mean_prec->Apply(*(sg_input.GetBlock(i)), *(sg_result.GetBlock(i))); } return 0; }
int Stokhos::ProductEpetraOperator:: Apply(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { if (useTranspose) { EpetraExt::BlockMultiVector sg_input(View, *range_base_map, Input); Epetra_MultiVector tmp(Result.Map(), Result.NumVectors()); Result.PutScalar(0.0); for (int i=0; i<coeff_.size(); i++) { coeff_[i]->Apply(*(sg_input.GetBlock(i)), tmp); Result.Update(1.0, tmp, 1.0); } } else { EpetraExt::BlockMultiVector sg_result(View, *range_base_map, Result); for (int i=0; i<coeff_.size(); i++) coeff_[i]->Apply(Input, *(sg_result.GetBlock(i))); } return 0; }
int Stokhos::MatrixFreeOperator:: Apply(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SG Operator Apply()"); #endif // Note for transpose: // The stochastic matrix is symmetric, however the matrix blocks may not // be. So the algorithm here is the same whether we are using the transpose // or not. We just apply the transpose of the blocks in the case of // applying the global transpose, and make sure the imported Input // vectors use the right map. // We have to be careful if Input and Result are the same vector. // If this is the case, the only possible solution is to make a copy const Epetra_MultiVector *input = &Input; bool made_copy = false; if (Input.Values() == Result.Values() && !is_stoch_parallel) { input = new Epetra_MultiVector(Input); made_copy = true; } // Initialize Result.PutScalar(0.0); const Epetra_Map* input_base_map = domain_base_map.get(); const Epetra_Map* result_base_map = range_base_map.get(); if (useTranspose == true) { input_base_map = range_base_map.get(); result_base_map = domain_base_map.get(); } // Allocate temporary storage int m = Input.NumVectors(); if (useTranspose == false && (tmp == Teuchos::null || tmp->NumVectors() != m*max_num_mat_vec)) tmp = Teuchos::rcp(new Epetra_MultiVector(*result_base_map, m*max_num_mat_vec)); else if (useTranspose == true && (tmp_trans == Teuchos::null || tmp_trans->NumVectors() != m*max_num_mat_vec)) tmp_trans = Teuchos::rcp(new Epetra_MultiVector(*result_base_map, m*max_num_mat_vec)); Epetra_MultiVector *tmp_result; if (useTranspose == false) tmp_result = tmp.get(); else tmp_result = tmp_trans.get(); // Map input into column map const Epetra_MultiVector *tmp_col; if (!is_stoch_parallel) tmp_col = input; else { if (useTranspose == false) { if (input_col == Teuchos::null || input_col->NumVectors() != m) input_col = Teuchos::rcp(new Epetra_MultiVector(*global_col_map, m)); input_col->Import(*input, *col_importer, Insert); tmp_col = input_col.get(); } else { if (input_col_trans == Teuchos::null || input_col_trans->NumVectors() != m) input_col_trans = Teuchos::rcp(new Epetra_MultiVector(*global_col_map_trans, m)); input_col_trans->Import(*input, *col_importer_trans, Insert); tmp_col = input_col_trans.get(); } } // Extract blocks EpetraExt::BlockMultiVector sg_input(View, *input_base_map, *tmp_col); EpetraExt::BlockMultiVector sg_result(View, *result_base_map, Result); for (int i=0; i<input_block.size(); i++) input_block[i] = sg_input.GetBlock(i); for (int i=0; i<result_block.size(); i++) result_block[i] = sg_result.GetBlock(i); // Apply block SG operator via // w_i = // \sum_{j=0}^P \sum_{k=0}^L J_k v_j < \psi_i \psi_j \psi_k > / <\psi_i^2> // for i=0,...,P where P = expansion_size, L = num_blocks, w_j is the jth // input block, w_i is the ith result block, and J_k is the kth block operator // k_begin and k_end are initialized in the constructor const Teuchos::Array<double>& norms = sg_basis->norm_squared(); for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) { int k = index(k_it); Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it); Cijk_type::kj_iterator j_end = Cijk->j_end(k_it); int nj = Cijk->num_j(k_it); if (nj > 0) { Teuchos::Array<double*> j_ptr(nj*m); Teuchos::Array<int> mj_indices(nj*m); int l = 0; for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) { int j = index(j_it); for (int mm=0; mm<m; mm++) { j_ptr[l*m+mm] = (*input_block[j])[mm]; mj_indices[l*m+mm] = l*m+mm; } l++; } Epetra_MultiVector input_tmp(View, *input_base_map, &j_ptr[0], nj*m); Epetra_MultiVector result_tmp(View, *tmp_result, &mj_indices[0], nj*m); if (use_block_apply) { (*block_ops)[k].Apply(input_tmp, result_tmp); } else { for (int jj=0; jj<nj*m; jj++) (*block_ops)[k].Apply(*(input_tmp(jj)), *(result_tmp(jj))); } l = 0; for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) { int j = index(j_it); for (Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it); i_it != Cijk->i_end(j_it); ++i_it) { int i = index(i_it); double c = value(i_it); if (scale_op) { int i_gid; if (useTranspose) i_gid = epetraCijk->GCID(j); else i_gid = epetraCijk->GRID(i); c /= norms[i_gid]; } for (int mm=0; mm<m; mm++) (*result_block[i])(mm)->Update(c, *result_tmp(l*m+mm), 1.0); } l++; } } } // Destroy blocks for (int i=0; i<input_block.size(); i++) input_block[i] = Teuchos::null; for (int i=0; i<result_block.size(); i++) result_block[i] = Teuchos::null; if (made_copy) delete input; return 0; }
int Stokhos::KLMatrixFreeOperator:: Apply(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { // We have to be careful if Input and Result are the same vector. // If this is the case, the only possible solution is to make a copy const Epetra_MultiVector *input = &Input; bool made_copy = false; if (Input.Values() == Result.Values() && !is_stoch_parallel) { input = new Epetra_MultiVector(Input); made_copy = true; } // Initialize Result.PutScalar(0.0); const Epetra_Map* input_base_map = domain_base_map.get(); const Epetra_Map* result_base_map = range_base_map.get(); if (useTranspose == true) { input_base_map = range_base_map.get(); result_base_map = domain_base_map.get(); } // Allocate temporary storage int m = Input.NumVectors(); if (useTranspose == false && (tmp == Teuchos::null || tmp->NumVectors() != m*max_num_mat_vec)) tmp = Teuchos::rcp(new Epetra_MultiVector(*result_base_map, m*max_num_mat_vec)); else if (useTranspose == true && (tmp_trans == Teuchos::null || tmp_trans->NumVectors() != m*max_num_mat_vec)) tmp_trans = Teuchos::rcp(new Epetra_MultiVector(*result_base_map, m*max_num_mat_vec)); Epetra_MultiVector *tmp_result; if (useTranspose == false) tmp_result = tmp.get(); else tmp_result = tmp_trans.get(); // Map input into column map const Epetra_MultiVector *tmp_col; if (!is_stoch_parallel) tmp_col = input; else { if (useTranspose == false) { if (input_col == Teuchos::null || input_col->NumVectors() != m) input_col = Teuchos::rcp(new Epetra_MultiVector(*global_col_map, m)); input_col->Import(*input, *col_importer, Insert); tmp_col = input_col.get(); } else { if (input_col_trans == Teuchos::null || input_col_trans->NumVectors() != m) input_col_trans = Teuchos::rcp(new Epetra_MultiVector(*global_col_map_trans, m)); input_col_trans->Import(*input, *col_importer_trans, Insert); tmp_col = input_col_trans.get(); } } // Extract blocks EpetraExt::BlockMultiVector sg_input(View, *input_base_map, *tmp_col); EpetraExt::BlockMultiVector sg_result(View, *result_base_map, Result); for (int i=0; i<input_block.size(); i++) input_block[i] = sg_input.GetBlock(i); for (int i=0; i<result_block.size(); i++) result_block[i] = sg_result.GetBlock(i); int N = result_block[0]->MyLength(); const Teuchos::Array<double>& norms = sg_basis->norm_squared(); int d = sg_basis->dimension(); Teuchos::Array<double> zero(d), one(d); for(int j = 0; j<d; j++) { zero[j] = 0.0; one[j] = 1.0; } Teuchos::Array< double > phi_0(expansion_size), phi_1(expansion_size); sg_basis->evaluateBases(zero, phi_0); sg_basis->evaluateBases(one, phi_1); // k_begin and k_end are initialized in the constructor for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) { Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it); Cijk_type::kj_iterator j_end = Cijk->j_end(k_it); int k = index(k_it); int nj = Cijk->num_j(k_it); if (nj > 0) { Teuchos::Array<double*> j_ptr(nj*m); Teuchos::Array<int> mj_indices(nj*m); int l = 0; for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) { int j = index(j_it); for (int mm=0; mm<m; mm++) { j_ptr[l*m+mm] = input_block[j]->Values()+mm*N; mj_indices[l*m+mm] = l*m+mm; } l++; } Epetra_MultiVector input_tmp(View, *input_base_map, &j_ptr[0], nj*m); Epetra_MultiVector result_tmp(View, *tmp_result, &mj_indices[0], nj*m); (*block_ops)[k].Apply(input_tmp, result_tmp); l = 0; for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) { int j = index(j_it); int j_gid = epetraCijk->GCID(j); for (Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it); i_it != Cijk->i_end(j_it); ++i_it) { int i = index(i_it); int i_gid = epetraCijk->GRID(i); double c = value(i_it); if (k == 0) c /= phi_0[0]; else { c /= phi_1[k]; if (i_gid == j_gid) c -= phi_0[k]/(phi_1[k]*phi_0[0])*norms[i_gid]; } if (scale_op) { if (useTranspose) c /= norms[j_gid]; else c /= norms[i_gid]; } for (int mm=0; mm<m; mm++) (*result_block[i])(mm)->Update(c, *result_tmp(l*m+mm), 1.0); } l++; } } } // Destroy blocks for (int i=0; i<input_block.size(); i++) input_block[i] = Teuchos::null; for (int i=0; i<result_block.size(); i++) result_block[i] = Teuchos::null; if (made_copy) delete input; return 0; }