double compute_residual_norm2(fei::LinearSystem& fei_ls, fei::Vector& r) { fei::SharedPtr<fei::Matrix> A = fei_ls.getMatrix(); fei::SharedPtr<fei::Vector> x = fei_ls.getSolutionVector(); fei::SharedPtr<fei::Vector> b = fei_ls.getRHS(); //form r = A*x A->multiply(x.get(), &r); //form r = b - r (i.e., r = b - A*x) r.update(1, b.get(), -1); //!!!!!! fix this !!!!!!!!! //terrible data copy. fei::Vector should provide a norm operation instead //of making me roll my own here... std::vector<int> indices; r.getVectorSpace()->getIndices_Owned(indices); std::vector<double> coefs(indices.size()); r.copyOut(indices.size(), &indices[0], &coefs[0]); double local_sum = 0; for(size_t i=0; i<indices.size(); ++i) { local_sum += coefs[i]*coefs[i]; } #ifdef HAVE_MPI MPI_Comm comm = r.getVectorSpace()->getCommunicator(); double global_sum = 0; int num_doubles = 1; MPI_Allreduce(&local_sum, &global_sum, num_doubles, MPI_DOUBLE, MPI_SUM, comm); #else double global_sum = local_sum; #endif return std::sqrt(global_sum); }
void copy_vector_to_mesh( fei::Vector & vec, const DofMapper & dof, stk_classic::mesh::BulkData & mesh_bulk_data ) { vec.scatterToOverlap(); std::vector<int> shared_and_owned_indices; vec.getVectorSpace()->getIndices_SharedAndOwned(shared_and_owned_indices); size_t num_values = shared_and_owned_indices.size(); if(num_values == 0) { return; } std::vector<double> values(num_values); vec.copyOut(num_values,&shared_and_owned_indices[0],&values[0]); stk_classic::mesh::EntityRank ent_type; stk_classic::mesh::EntityId ent_id; const stk_classic::mesh::FieldBase * field; int offset_into_field; for(size_t i = 0; i < num_values; ++i) { dof.get_dof( shared_and_owned_indices[i], ent_type, ent_id, field, offset_into_field ); stk_classic::mesh::Entity & entity = *mesh_bulk_data.get_entity(ent_type, ent_id); void * data = stk_classic::mesh::field_data(*field,entity); if(!(field->type_is<double>()) || data == NULL) { std::ostringstream oss; oss << "stk_classic::linsys::copy_vector_to_mesh ERROR, bad data type, or "; oss << " field (" << field->name() << ") not found on entity with type " << entity.entity_rank(); oss << " and ID " << entity.identifier(); std::string str = oss.str(); throw std::runtime_error(str.c_str()); } double * double_data = reinterpret_cast<double *>(data); double_data[offset_into_field] = values[i]; } }
bool confirm_vector_values(const fei::Vector& vec, double expected_value) { std::vector<int> indices; fei::SharedPtr<fei::VectorSpace> vspace = vec.getVectorSpace(); vspace->getIndices_Owned(indices); bool result = true; if (indices.size() > 0) { std::vector<double> coefs(indices.size()); vec.copyOut(indices.size(), &indices[0], &coefs[0]); for(size_t i=0; i<indices.size(); ++i) { if (std::abs(coefs[i] - expected_value) > 1.e-13) { result = false; break; } } } return result; }
void scale_vector(double scalar, fei::Vector& vec) { fei::SharedPtr<fei::VectorSpace> vspace = vec.getVectorSpace(); int numIndices = vspace->getNumIndices_Owned(); std::vector<int> indices(numIndices); vspace->getIndices_Owned(numIndices, &indices[0], numIndices); std::vector<double> coefs(numIndices); vec.copyOut(numIndices, &indices[0], &coefs[0]); for(size_t j=0; j<coefs.size(); ++j) { coefs[j] *= scalar; } vec.copyIn(numIndices, &indices[0], &coefs[0]); }
void add_vector_to_vector(double scalar, const fei::Vector& src_vector, fei::Vector& dest_vector) { fei::SharedPtr<fei::VectorSpace> vspace = src_vector.getVectorSpace(); int numIndices = vspace->getNumIndices_Owned(); std::vector<int> indices(numIndices); vspace->getIndices_Owned(numIndices, &indices[0], numIndices); std::vector<double> coefs(numIndices); src_vector.copyOut(numIndices, &indices[0], &coefs[0]); for(size_t j=0; j<coefs.size(); ++j) { coefs[j] *= scalar; } dest_vector.sumIn(numIndices, &indices[0], &coefs[0]); }
void assemble_elem_matrices_and_vectors(stk::mesh::BulkData& mesh, stk::mesh::FieldBase& field, stk::linsys::DofMapper& dof_mapper, fei::Matrix& matrix, fei::Vector& rhs) { stk::mesh::fem::FEMMetaData &fem = stk::mesh::fem::FEMMetaData::get(mesh); const stk::mesh::EntityRank element_rank = fem.element_rank(); const std::vector<stk::mesh::Bucket*>& mesh_buckets = mesh.buckets(element_rank); std::vector<stk::mesh::Bucket*> part_buckets; stk::mesh::Selector select_owned(stk::mesh::MetaData::get(mesh).locally_owned_part()); stk::mesh::get_buckets(select_owned, mesh_buckets, part_buckets); int field_id = dof_mapper.get_field_id(field); stk::mesh::Entity& first_entity = *(part_buckets[0]->begin()); stk::mesh::PairIterRelation rel = first_entity.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); int num_nodes_per_elem = rel.second - rel.first; fei::SharedPtr<fei::MatrixGraph> matgraph = matrix.getMatrixGraph(); int pattern_id = matgraph->definePattern(num_nodes_per_elem, stk::mesh::fem::FEMMetaData::NODE_RANK, field_id); std::vector<int> node_ids(num_nodes_per_elem); const int field_size = dof_mapper.get_fei_VectorSpace()->getFieldSize(field_id); const int matsize = num_nodes_per_elem*field_size*num_nodes_per_elem*field_size; const int vecsize = num_nodes_per_elem*field_size; std::vector<double> elem_matrix_1d(matsize, 0); std::vector<double*> elem_matrix_2d(vecsize); std::vector<double> elem_vector(vecsize, 0); for(size_t i=0; i<elem_matrix_2d.size(); ++i) { elem_matrix_2d[i] = &elem_matrix_1d[i*vecsize]; } //fill our dummy elem-matrix: //This dummy matrix will be the same for every element. A real application //would form a different elem-matrix for each element. for(size_t i=0; i<elem_matrix_2d.size(); ++i) { double* row = elem_matrix_2d[i]; if (i>=1) row[i-1] = -1; row[i] = 2; if (i<elem_matrix_2d.size()-1) row[i+1] = -1; elem_vector[i] = 1; } std::vector<int> eqn_indices(vecsize); for(size_t i=0; i<part_buckets.size(); ++i) { stk::mesh::Bucket::iterator b_iter = part_buckets[i]->begin(), b_end = part_buckets[i]->end(); for(; b_iter != b_end; ++b_iter) { stk::mesh::Entity& elem = *b_iter; rel = elem.relations(stk::mesh::fem::FEMMetaData::NODE_RANK); for(int j=0; rel.first != rel.second; ++rel.first, ++j) { node_ids[j] = rel.first->entity()->identifier(); } matgraph->getPatternIndices(pattern_id, &node_ids[0], eqn_indices); matrix.sumIn(vecsize, &eqn_indices[0], vecsize, &eqn_indices[0], &elem_matrix_2d[0]); rhs.sumIn(vecsize, &eqn_indices[0], &elem_vector[0]); } } }