int main(int argc, char *argv[]) { // Test array-array inner product double v1 [5] = {0, 1, 2, 3, 4}; double v2 [5] = {4, 3, 2, 1, 0}; double result = 10; int len = 5; assert(innerProduct(v1,v2,len)==result && "tools - innerProduct, array-array gave an unexpected result"); // Test vector-vector inner product std::vector<double> vv1, vv2; for (int i=0;i<len;i++) { vv1.push_back(v1[i]); vv2.push_back(v2[i]); } assert(innerProduct(vv1,vv2)==result && "tools - innerProduct, vector-vector gave an unexpected result"); // Test Vector-Vector inner product Vector vvv1, vvv2; for (int i=0;i<len;i++) { vvv1.push_back(vv1); vvv2.push_back(vv2); } assert(innerProduct(vvv1,vvv2)==(len*result) && "tools - innerProduct, Vector-Vector gave an unexpected result"); // Test sparse Vector-Vector inner product IntVector sparse; for (int i=0;i<len;i++) { sparse.push_back(std::vector<int>()); sparse[i].push_back(i); } assert(innerProduct(vvv1,vvv2,sparse)==result && "tools - innerProduct, sparse Vector-Vector gave an unexpected result"); return 0; }
bool rayIntersectsTriangle(const float *p,const float *d,const float *v0,const float *v1,const float *v2,float &t) { float e1[3],e2[3],h[3],s[3],q[3]; float a,f,u,v; vector(e1,v1,v0); vector(e2,v2,v0); crossProduct(h,d,e2); a = innerProduct(e1,h); if (a > -0.00001 && a < 0.00001) return(false); f = 1/a; vector(s,p,v0); u = f * (innerProduct(s,h)); if (u < 0.0 || u > 1.0) return(false); crossProduct(q,s,e1); v = f * innerProduct(d,q); if (v < 0.0 || u + v > 1.0) return(false); // at this stage we can compute t to find out where // the intersection point is on the line t = f * innerProduct(e2,q); if (t > 0) // ray intersection return(true); else // this means that there is a line intersection // but not a ray intersection return (false); }
double SCL::flux(const Point<DIM>& p, double u_l, double u_r, const std::vector<double>& n) const { std::vector<double> f_l((*_f_)(p, u_l)); std::vector<double> f_r((*_f_)(p, u_r)); double alpha0 = (*_v_)(p, u_l); double alpha1 = (*_v_)(p, u_r); double alpha = std::max(alpha0, alpha1); return 0.5*((innerProduct(f_l, n) + innerProduct(f_r, n)) - alpha*(u_r - u_l)); }
/** input: n -- normal, v0 -- a point on plane p0, p1 -- define a vector output: pr -- intersection point r = dot(n,(v0-p0))/dot(n,(p1-p0)) pr = p0+r*(p1-p0) */ GLfloat pointOnIntersectsPlaneEllipsoid(GLfloat n[3], GLfloat v0[3], GLfloat p0[3], GLfloat p1[3], GLfloat pr[3]) { GLfloat r; GLfloat v1[3], v2[3]; vector(v1, v0, p0); vector(v2, p1, p0); r = innerProduct(n, v1) / innerProduct(n, v2); pr[0] = r * v2[0] + p0[0]; pr[1] = r * v2[1] + p0[1]; pr[2] = r * v2[2] + p0[2]; return r; }
float distancePointLineOnPlane (vector_t const point, const line_t line, const plane_t plane) { vector_t normal_in_plane = normalizeVector(crossProduct( line.direction, plane.normal)); return innerProduct(subtractVectors(point,line.point),normal_in_plane); }
/** input n -- normal, v0 -- a point on plane P -- object point output P1 --projection point on the plane */ void projectionOnPlane(GLfloat n[3], GLfloat V0[3], GLfloat P[3], GLfloat P1[3]) { GLfloat V0P[3]; vector(V0P, P, V0); normalize(n); productVectorScaler(n, innerProduct(V0P, n) , V0P); vector(P1, P, V0P); }
void ISOP2P1::getMonitor() { /// 限制最大迭代步数. maxStep() = max_step; /// 同步网格. syncMesh(); FEMFunction<double, DIM> _u_h(fem_space_p); FEMFunction<double, DIM> _v_h(fem_space_p); Operator::L2Interpolate(v_h[0], _u_h); Operator::L2Interpolate(v_h[1], _v_h); FEMSpace<double, DIM>::ElementIterator the_element = fem_space_p.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element = fem_space_p.endElement(); for (int i = 0; the_element != end_element; ++the_element) { double volume = the_element->templateElement().volume(); const QuadratureInfo<DIM>& quad_info = the_element->findQuadratureInfo(3); std::vector<double> jacobian = the_element->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<DIM> > q_point = the_element->local_to_global(quad_info.quadraturePoint()); std::vector<std::vector<double> > basis_value = the_element->basis_function_value(q_point); std::vector<double> u_h_value = _u_h.value(q_point, *the_element); std::vector<double> v_h_value = _v_h.value(q_point, *the_element); std::vector<std::vector<double> > u_h_gradient = _u_h.gradient(q_point, *the_element); std::vector<std::vector<double> > v_h_gradient = _v_h.gradient(q_point, *the_element); float d = 0, area = 0, norm = 0; for (int l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; area += Jxw; norm += u_h_value[l] * u_h_value[l] + v_h_value[l] * v_h_value[l]; d += Jxw * (innerProduct(u_h_gradient[l], u_h_gradient[l]) + innerProduct(v_h_gradient[l], v_h_gradient[l])); } norm = 1.0 / (eps + sqrt(norm)); monitor(i++) = d / area; } std::cout << "max monitor=" << *std::max_element(monitor().begin(), monitor().end()) << "\tmin monitor=" << *std::min_element(monitor().begin(), monitor().end()) << std::endl; double max_monitor = *std::max_element(monitor().begin(), monitor().end()); smoothMonitor(2); for (int i = 0; i < n_geometry(2); ++i) monitor(i) = 1.0 / sqrt(1.0 + alpha * monitor(i) * monitor(i)); };
double kernel(vector<double> a, vector<double> b) { // double distance; // cout.precision(19); // distance = absDistance(a, b); // distance = pow(distance, 2); // double temp = exp(-sigma * distance); // return temp; return exp(-sigma*(pow(v_length(a),2) + pow(v_length(b),2)- 2 * innerProduct(a,b))); }
static void findCircle3pts(Point2f *pts, Point2f ¢er, float &radius) { // two edges of the triangle v1, v2 Point2f v1 = pts[1] - pts[0]; Point2f v2 = pts[2] - pts[0]; if (innerProduct(v1, v2) == 0.0f) { // v1, v2 colineation, can not determine a unique circle // find the longtest distance as diameter line float d1 = (float)norm(pts[0] - pts[1]); float d2 = (float)norm(pts[0] - pts[2]); float d3 = (float)norm(pts[1] - pts[2]); if (d1 >= d2 && d1 >= d3) { center = (pts[0] + pts[1]) / 2.0f; radius = (d1 / 2.0f); } else if (d2 >= d1 && d2 >= d3) { center = (pts[0] + pts[2]) / 2.0f; radius = (d2 / 2.0f); } else if (d3 >= d1 && d3 >= d2) { center = (pts[1] + pts[2]) / 2.0f; radius = (d3 / 2.0f); } } else { // center is intersection of midperpendicular lines of the two edges v1, v2 // a1*x + b1*y = c1 where a1 = v1.x, b1 = v1.y // a2*x + b2*y = c2 where a2 = v2.x, b2 = v2.y Point2f midPoint1 = (pts[0] + pts[1]) / 2.0f; float c1 = midPoint1.x * v1.x + midPoint1.y * v1.y; Point2f midPoint2 = (pts[0] + pts[2]) / 2.0f; float c2 = midPoint2.x * v2.x + midPoint2.y * v2.y; float det = v1.x * v2.y - v1.y * v2.x; float cx = (c1 * v2.y - c2 * v1.y) / det; float cy = (v1.x * c2 - v2.x * c1) / det; center.x = (float)cx; center.y = (float)cy; cx -= pts[0].x; cy -= pts[0].y; radius = (float)(std::sqrt(cx *cx + cy * cy)); } }
void ISOP2P1::updateSolution() { /// 更新插值点. fem_space_p.updateDofInterpPoint(); fem_space_v.updateDofInterpPoint(); /// 备份数值解. FEMFunction<double, DIM> _u_h(v_h[0]); FEMFunction<double, DIM> _v_h(v_h[1]); FEMFunction<double, DIM> _p_h(p_h); const double& msl = moveStepLength(); /// 因为有限元空间插值点变化, 重新构造矩阵. buildMatrixStruct(); buildMatrix(); /// 因为网格移动量为小量, 因此时间步长可以相对取的大些. double _dt = 0.1; int n_dof_v = fem_space_v.n_dof(); int n_dof_p = fem_space_p.n_dof(); int n_total_dof = DIM * n_dof_v + n_dof_p; int n_total_dof_v = DIM * n_dof_v; /// 一步Euler. for (int m = 1; m > 0; --m) { /// 系数矩阵直接使用 Stokes 矩阵结构. SparseMatrix<double> mat_moving; mat_moving.reinit(sp_stokes); /// (0, 0) for (int i = 0; i < sp_vxvx.n_nonzero_elements(); ++i) mat_moving.global_entry(index_vxvx[i]) = mat_v_mass.global_entry(i); /// (1, 1) 这两个对角块仅有质量块. for (int i = 0; i < sp_vyvy.n_nonzero_elements(); ++i) mat_moving.global_entry(index_vyvy[i]) = mat_v_mass.global_entry(i); /// (0, 2) 这个不是方阵. 在矩阵结构定义的时候已经直接排除了对角元优 /// 先. for (int i = 0; i < sp_pvx.n_nonzero_elements(); ++i) mat_moving.global_entry(index_pvx[i]) = (1.0 / m) * mat_pvx_divT.global_entry(i); /// (1, 2) for (int i = 0; i < sp_pvy.n_nonzero_elements(); ++i) mat_moving.global_entry(index_pvy[i]) = (1.0 / m) * mat_pvy_divT.global_entry(i); /// (2, 0) for (int i = 0; i < sp_vxp.n_nonzero_elements(); ++i) mat_moving.global_entry(index_vxp[i]) = (1.0 / m) * mat_vxp_div.global_entry(i); /// (2, 1) 这四块直接复制散度矩阵. for (int i = 0; i < sp_vyp.n_nonzero_elements(); ++i) mat_moving.global_entry(index_vyp[i]) = (1.0 / m) * mat_vyp_div.global_entry(i); /// 问题的右端项. Vector<double> rhs_loc(n_total_dof); // rhs.reinit(n_total_dof); FEMSpace<double, DIM>::ElementIterator the_element_v = fem_space_v.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element_v = fem_space_v.endElement(); /// 遍历速度单元, 拼装相关系数矩阵和右端项. for (the_element_v = fem_space_v.beginElement(); the_element_v != end_element_v; ++the_element_v) { /// 当前单元信息. double volume = the_element_v->templateElement().volume(); /// 积分精度至少为2. const QuadratureInfo<DIM>& quad_info = the_element_v->findQuadratureInfo(4); std::vector<double> jacobian = the_element_v->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<DIM> > q_point = the_element_v->local_to_global(quad_info.quadraturePoint()); /// 速度单元信息. std::vector<std::vector<double> > basis_value_v = the_element_v->basis_function_value(q_point); std::vector<double> vx_value = _u_h.value(q_point, *the_element_v); std::vector<double> vy_value = _v_h.value(q_point, *the_element_v); std::vector<std::vector<double> > vx_gradient = v_h[0].gradient(q_point, *the_element_v); std::vector<std::vector<double> > vy_gradient = v_h[1].gradient(q_point, *the_element_v); const std::vector<int>& element_dof_v = the_element_v->dof(); int n_element_dof_v = the_element_v->n_dof(); /// 速度积分点上的移动方向, 注意是速度单元的积分点, 在压力单元上的移动方向. /// 所以下面一行程序, 仔细算过, 没有问题. std::vector<std::vector<double> > move_vector = moveDirection(q_point, index_v2p[the_element_v->index()]); for (int l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; for (int i = 0; i < n_element_dof_v; ++i) { double rhs_cont = (vx_value[l] + (1.0 / m) * msl * innerProduct(move_vector[l], vx_gradient[l])) * basis_value_v[i][l]; rhs_cont *= Jxw; rhs_loc(element_dof_v[i]) += rhs_cont; rhs_cont = (vy_value[l] + (1.0 / m) * msl * innerProduct(move_vector[l], vy_gradient[l])) * basis_value_v[i][l]; rhs_cont *= Jxw; rhs_loc(n_dof_v + element_dof_v[i]) += rhs_cont; } } } /// 构建系数矩阵和右端项. Vector<double> x(n_total_dof); // PoiseuilleVx real_vx (-1.0, 1.0); // PoiseuilleVy real_vy; // Operator::L2Project(real_vx, v_h[0], Operator::LOCAL_LEAST_SQUARE, 3); // Operator::L2Project(real_vy, v_h[1], Operator::LOCAL_LEAST_SQUARE, 3); // /// 边界处理. const std::size_t * rowstart = sp_stokes.get_rowstart_indices(); const unsigned int * colnum = sp_stokes.get_column_numbers(); /// 遍历全部维度的速度节点. for (unsigned int i = 0; i < n_total_dof_v; ++i) { /// 边界标志. int bm = -1; /// 判断一下是 x 方向还是 y 方向. 分别读取标志. if (i < n_dof_v) bm = fem_space_v.dofInfo(i).boundary_mark; else bm = fem_space_v.dofInfo(i - n_dof_v).boundary_mark; if (bm == 0) continue; /// 方腔流边界条件. if (bm == 1 || bm == 2 || bm == 4 || bm == 5) x(i) = 0.0; if (bm == 3) if (i < n_dof_v) { /// 不包括顶端的两个端点,称为watertight cavity. // x(i) = scale * 1.0; Regularized regularize; x(i) = scale * regularize.value(fem_space_v.dofInfo(i).interp_point); } else x(i) = 0.0; // /// poiseuille flow边界条件. // if (bm == 1 || bm == 2 || bm == 4 || bm == 5) // if (i < n_dof_v) // x(i) = scale * real_vx.value(fem_space_v.dofInfo(i).interp_point); // else // x(i) = scale * real_vy.value(fem_space_v.dofInfo(i - n_dof_v).interp_point); /// 右端项这样改, 如果该行和列其余元素均为零, 则在迭代中确 /// 保该数值解和边界一致. if (bm == 1 || bm == 2 || bm == 3 || bm == 4 || bm == 5) // if (bm == 1 || bm == 2 || bm == 4 || bm == 5) { rhs_loc(i) = mat_moving.diag_element(i) * x(i); /// 遍历 i 行. for (unsigned int j = rowstart[i] + 1; j < rowstart[i + 1]; ++j) { /// 第 j 个元素消成零(不是第 j 列!). 注意避开了对角元. mat_moving.global_entry(j) -= mat_moving.global_entry(j); /// 第 j 个元素是第 k 列. unsigned int k = colnum[j]; /// 看看第 k 行的 i 列是否为零元. const unsigned int *p = std::find(&colnum[rowstart[k] + 1], &colnum[rowstart[k + 1]], i); /// 如果是非零元. 则需要将这一项移动到右端项. 因为第 i 个未知量已知. if (p != &colnum[rowstart[k + 1]]) { /// 计算 k 行 i 列的存储位置. unsigned int l = p - &colnum[rowstart[0]]; /// 移动到右端项. 等价于 r(k) = r(k) - x(i) * A(k, i). rhs_loc(k) -= mat_moving.global_entry(l) * x(i); /// 移完此项自然是零. mat_moving.global_entry(l) -= mat_moving.global_entry(l); } } } } std::cout << "boundary values for updateSolution OK!" << std::endl; // /// debug 边界条件处理部分,已经测试过, 边界处理正确. // RegularMesh<DIM> &mesh_v = irregular_mesh_v->regularMesh(); // for (int i = 0; i < mesh_v.n_geometry(0); ++i) // { // Point<DIM> &p= mesh_v.point(i); // if (fabs(1 - p[1]) < eps || fabs(1 - p[0]) < eps || fabs(-1 - p[1]) < eps || fabs(-1 - p[0]) < eps) // { // std::cout << "point(" << i << ") = (" << p[0] << "," << p[1] << ");" << std::endl; // std::cout << "uh(" << i << ") = " << v_h[0](i) << std::endl; // std::cout << "vh(" << i << ") = " << v_h[1](i) << std::endl; // } // } // getchar(); // /// debug clock_t t_cost = clock(); /// 预处理矩阵. /// 不完全LU分解. dealii::SparseILU <double> preconditioner; preconditioner.initialize(mat_moving); /// 矩阵求解. dealii::SolverControl solver_control (4000000, l_tol, check); SolverMinRes<Vector<double> > minres (solver_control); minres.solve (mat_moving, x, rhs_loc, PreconditionIdentity()); t_cost = clock() - t_cost; std::cout << "time cost: " << (((float)t_cost) / CLOCKS_PER_SEC) << std::endl; for (int i = 0; i < n_dof_v; ++i) { v_h[0](i) = x(i); v_h[1](i) = x(i + n_dof_v); } for (int i = 0; i < n_dof_p; ++i) p_h(i) = x(i + 2 * n_dof_v); /// debug std::ofstream mat_deb; // rowstart = sp_pvx.get_rowstart_indices(); // colnum = sp_pvx.get_column_numbers(); mat_deb.open("mat.m", std::ofstream::out); mat_deb.setf(std::ios::fixed); mat_deb.precision(20); for (int i = 0; i < n_total_dof; ++i) { for (int j = rowstart[i]; j < rowstart[i + 1]; ++j) { mat_deb << "A(" << i + 1 << ", " << colnum[j] + 1 << ")=" << mat_moving.global_entry(j) << ";" << std::endl; } mat_deb << "x(" << i + 1<< ") = " << x(i) << ";" << std::endl; mat_deb << "rhs(" << i + 1 << ") = " << rhs_loc(i) << ";" << std::endl; } // for(int i = 0; i < n_dof_p; ++i) // mat_deb << "x(" << i + 1<< ") = " << p_h(i) << ";" << std::endl; mat_deb.close(); std::cout << "mat output" << std::endl; Vector<double> res(n_total_dof); mat_moving.vmult(res, x); res *= -1; res += rhs_loc; std::cout << "res_l2norm =" << res.l2_norm() << std::endl; // double error; // error = Functional::L2Error(v_h[0], real_vx, 3); // std::cout << "|| u - u_h ||_L2 = " << error << std::endl; // error = Functional::H1SemiError(v_h[0], real_vx, 3); // std::cout << "|| u - u_h ||_H1 = " << error << std::endl; /// debug RegularMesh<DIM> &mesh_p = irregular_mesh_p->regularMesh(); for (int i = 0; i < mesh_p.n_geometry(0); ++i) { (*mesh_p.h_geometry<0>(i))[0] += moveDirection(i)[0]; (*mesh_p.h_geometry<0>(i))[1] += moveDirection(i)[1]; } /// 输出一下. outputTecplotP("NS_Euler"); getchar(); } };
int main(int argc, char * argv[]) { typedef MPI::HGeometryForest<DIM,DOW> forest_t; typedef MPI::BirdView<forest_t> ir_mesh_t; typedef FEMSpace<double,DIM,DOW> fe_space_t; typedef MPI::DOF::GlobalIndex<forest_t, fe_space_t> global_index_t; MPI_Init(&argc, &argv); forest_t forest(MPI_COMM_WORLD); ir_mesh_t ir_mesh; MPI::load_mesh(argv[1], forest, ir_mesh); /// 从一个目录中读入网格数据 int round = 0; if (argc >= 3) round = atoi(argv[2]); ir_mesh.globalRefine(round); ir_mesh.semiregularize(); ir_mesh.regularize(false); TemplateGeometry<DIM> tri; tri.readData("triangle.tmp_geo"); CoordTransform<DIM,DIM> tri_ct; tri_ct.readData("triangle.crd_trs"); TemplateDOF<DIM> tri_td(tri); tri_td.readData("triangle.1.tmp_dof"); BasisFunctionAdmin<double,DIM,DIM> tri_bf(tri_td); tri_bf.readData("triangle.1.bas_fun"); std::vector<TemplateElement<double,DIM,DIM> > tmp_ele(1); tmp_ele[0].reinit(tri, tri_td, tri_ct, tri_bf); RegularMesh<DIM,DOW>& mesh = ir_mesh.regularMesh(); fe_space_t fem_space(mesh, tmp_ele); u_int n_ele = mesh.n_geometry(DIM); fem_space.element().resize(n_ele); for (int i = 0;i < n_ele;i ++) { fem_space.element(i).reinit(fem_space, i, 0); } fem_space.buildElement(); fem_space.buildDof(); fem_space.buildDofBoundaryMark(); std::cout << "Building global indices ... " << std::flush; global_index_t global_index(forest, fem_space); global_index.build(); std::cout << "OK!" << std::endl; Epetra_MpiComm comm(forest.communicator()); Epetra_Map map(global_index.n_global_dof(), global_index.n_primary_dof(), 0, comm); global_index.build_epetra_map(map); /// 构造 Epetra 的分布式稀疏矩阵模板 std::cout << "Build sparsity pattern ... " << std::flush; Epetra_FECrsGraph G(Copy, map, 10); fe_space_t::ElementIterator the_ele = fem_space.beginElement(), end_ele = fem_space.endElement(); for (;the_ele != end_ele;++ the_ele) { const std::vector<int>& ele_dof = the_ele->dof(); u_int n_ele_dof = ele_dof.size(); /** * 建立从局部自由度数组到全局自由度数组的映射表,这是实现分布式并行 * 状态下的数据结构的关键一步。 */ std::vector<int> indices(n_ele_dof); for (u_int i = 0;i < n_ele_dof;++ i) { indices[i] = global_index(ele_dof[i]); } G.InsertGlobalIndices(n_ele_dof, &indices[0], n_ele_dof, &indices[0]); } G.GlobalAssemble(); std::cout << "OK!" << std::endl; /// 准备构造 Epetra 的分布式稀疏矩阵和计算分布式右端项 std::cout << "Build sparse matrix ... " << std::flush; Epetra_FECrsMatrix A(Copy, G); Epetra_FEVector b(map); the_ele = fem_space.beginElement(); for (;the_ele != end_ele;++ the_ele) { double vol = the_ele->templateElement().volume(); const QuadratureInfo<DIM>& qi = the_ele->findQuadratureInfo(5); std::vector<Point<DIM> > q_pnt = the_ele->local_to_global(qi.quadraturePoint()); int n_q_pnt = qi.n_quadraturePoint(); std::vector<double> jac = the_ele->local_to_global_jacobian(qi.quadraturePoint()); std::vector<std::vector<double> > bas_val = the_ele->basis_function_value(q_pnt); std::vector<std::vector<std::vector<double> > > bas_grad = the_ele->basis_function_gradient(q_pnt); const std::vector<int>& ele_dof = the_ele->dof(); u_int n_ele_dof = ele_dof.size(); FullMatrix<double> ele_mat(n_ele_dof, n_ele_dof); Vector<double> ele_rhs(n_ele_dof); for (u_int l = 0;l < n_q_pnt;++ l) { double JxW = vol*jac[l]*qi.weight(l); double f_val = _f_(q_pnt[l]); for (u_int i = 0;i < n_ele_dof;++ i) { for (u_int j = 0;j < n_ele_dof;++ j) { ele_mat(i, j) += JxW*(innerProduct(bas_grad[i][l], bas_grad[j][l])); } ele_rhs(i) += JxW*f_val*bas_val[i][l]; } } /** * 此处将单元矩阵和单元载荷先计算好,然后向全局的矩阵和载荷向量上 * 集中,可以提高效率。 */ std::vector<int> indices(n_ele_dof); for (u_int i = 0;i < n_ele_dof;++ i) { indices[i] = global_index(ele_dof[i]); } A.SumIntoGlobalValues(n_ele_dof, &indices[0], n_ele_dof, &indices[0], &ele_mat(0,0)); b.SumIntoGlobalValues(n_ele_dof, &indices[0], &ele_rhs(0)); } A.GlobalAssemble(); b.GlobalAssemble(); std::cout << "OK!" << std::endl; /// 准备解向量。 Epetra_FEVector x(map); /// 加上狄氏边值条件 u_int n_bnd_dof = 0; /// 首先清点边界上自由度的个数 for (u_int i = 0;i < fem_space.n_dof();++ i) { if (fem_space.dofBoundaryMark(i) > 0) { /// 如果不是在主几何体上就不做 if (! global_index.is_dof_on_primary_geometry(i)) continue; n_bnd_dof += 1; } } /// 准备空间存储边界上全局标号、自变量和右端项 std::vector<int> bnd_idx(n_bnd_dof); std::vector<double> x_entry(n_bnd_dof), rhs_entry(n_bnd_dof); /// 对自由度做循环 for (u_int i = 0, j = 0;i < fem_space.n_dof();++ i) { if (fem_space.dofBoundaryMark(i) > 0) { /// 边界上的自由度? /// 如果不是在主几何体上就不做 if (! global_index.is_dof_on_primary_geometry(i)) continue; const int& idx = global_index(i); /// 行的全局标号 bnd_idx[j] = idx; /// 修改矩阵 int lrid = A.LRID(idx); int row_nnz, *row_idx; double *row_entry, row_diag; A.ExtractMyRowView(lrid, row_nnz, row_entry, row_idx); /// 取出矩阵的行 for (int k = 0;k < row_nnz;++ k) { /// 对矩阵的行进行修改 if (A.LCID(row_idx[k]) != lrid) { /// 如果不是对角元 row_entry[k] = 0.0; /// 则将矩阵元素清零 } else { /// 而对角元保持不变 row_diag = row_entry[k]; /// 并记录下对角元 } } /// 计算并记下自变量和右端项,假设自由度值为插值量 double u_b_val = _u_b_(fem_space.dofInfo(i).interp_point); x_entry[j] = u_b_val; rhs_entry[j] = row_diag*u_b_val; j += 1; } } std::cout << "# DOF on the boundary: " << n_bnd_dof << std::endl; /// 修改解变量和右端项 x.ReplaceGlobalValues(n_bnd_dof, &bnd_idx[0], &x_entry[0]); b.ReplaceGlobalValues(n_bnd_dof, &bnd_idx[0], &rhs_entry[0]); /// 调用 AztecOO 的求解器。 std::cout << "Solving the linear system ..." << std::flush; Epetra_LinearProblem problem(&A, &x, &b); AztecOO solver(problem); ML_Epetra::MultiLevelPreconditioner precond(A, true); solver.SetPrecOperator(&precond); solver.SetAztecOption(AZ_solver, AZ_gmres); solver.SetAztecOption(AZ_output, 100); solver.Iterate(5000, 1.0e-12); std::cout << "OK!" << std::endl; Epetra_Map fe_map(-1, global_index.n_local_dof(), &global_index(0), 0, comm); FEMFunction<double,DIM> u_h(fem_space); Epetra_Import importer(fe_map, map); Epetra_Vector X(View, fe_map, &u_h(0)); X.Import(x, importer, Add); char filename[1024]; sprintf(filename, "u_h%d.dx", forest.rank()); u_h.writeOpenDXData(filename); MPI_Finalize(); return 0; }
float distancePointPlane (const vector_t point, const plane_t plane) { return innerProduct(point, plane.normal) - innerProduct(plane.point, plane.normal); }
void RBEC::stepForward() { int i, j, k, l; int n_dof = fem_space.n_dof(); int n_total_dof = 2 * n_dof; mat_RBEC.reinit(sp_RBEC); mat_rere.reinit(sp_rere); mat_reim.reinit(sp_reim); mat_imre.reinit(sp_imre); mat_imim.reinit(sp_imim); Vector<double> phi(n_total_dof); FEMFunction <double, DIM> phi_star(fem_space); Vector<double> rhs(n_total_dof); Potential V(gamma_x, gamma_y); /// 准备一个遍历全部单元的迭代器. FEMSpace<double, DIM>::ElementIterator the_element = fem_space.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element = fem_space.endElement(); /// 循环遍历全部单元, 只是为了统计每一行的非零元个数. for (; the_element != end_element; ++the_element) { /// 当前单元信息. double volume = the_element->templateElement().volume(); const QuadratureInfo<DIM>& quad_info = the_element->findQuadratureInfo(6); std::vector<double> jacobian = the_element->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<AFEPack::Point<DIM> > q_point = the_element->local_to_global(quad_info.quadraturePoint()); /// 单元信息. std::vector<std::vector<std::vector<double> > > basis_gradient = the_element->basis_function_gradient(q_point); std::vector<std::vector<double> > basis_value = the_element->basis_function_value(q_point); std::vector<double> phi_re_value = phi_re.value(q_point, *the_element); std::vector<double> phi_im_value = phi_im.value(q_point, *the_element); const std::vector<int>& element_dof = the_element->dof(); int n_element_dof = the_element->n_dof(); /// 实际拼装. for (l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; for (j = 0; j < n_element_dof; ++j) { for (k = 0; k < n_element_dof; ++k) { double cont = Jxw * ((1 / dt) * basis_value[j][l] * basis_value[k][l] + 0.5 * innerProduct(basis_gradient[j][l], basis_gradient[k][l]) + V.value(q_point[l]) * basis_value[j][l] * basis_value[k][l] + beta * (phi_re_value[l] * phi_re_value[l] + phi_im_value[l] * phi_im_value[l]) * basis_value[j][l] * basis_value[k][l]); mat_RBEC.add(element_dof[j], element_dof[k], cont); mat_RBEC.add(element_dof[j] + n_dof, element_dof[k] + n_dof, cont); } rhs(element_dof[j]) += Jxw * phi_re_value[l] * basis_value[j][l] / dt; rhs(element_dof[j] + n_dof) += Jxw * phi_im_value[l] * basis_value[j][l] / dt; } } } FEMFunction<double, DIM> _phi_re(phi_re); FEMFunction<double, DIM> _phi_im(phi_im); boundaryValue(phi, rhs, mat_RBEC); // AMGSolver solver(mat_RBEC); // solver.solve(phi, rhs); dealii::SolverControl solver_control(4000, 1e-15); SolverGMRES<Vector<double> >::AdditionalData para(500, false, true); SolverGMRES<Vector<double> > gmres(solver_control, para); gmres.solve(mat_RBEC, phi, rhs, PreconditionIdentity()); for (int i = 0; i < n_dof; ++i) { phi_re(i) = phi(i); phi_im(i) = phi(n_dof + i); } for (int i = 0; i < n_dof; ++i) phi_star(i) = sqrt(phi_re(i) * phi_re(i) + phi_im(i) * phi_im(i)); double L2Phi = Functional::L2Norm(phi_re, 6); std::cout << "L2 norm = " << L2Phi << std::endl; for (int i = 0; i < n_dof; ++i) { phi_re(i) /= L2Phi; phi_im(i) /= L2Phi; } double e = energy(phi_re, phi_im, 6); std::cout << "Energy = " << e << std::endl; t += dt; };
vector<vector<double>> computeGramSchmidt(double v1[3], double v2[3], double v3[3]) { double u1[3]; u1[0] = v1[0]; u1[1] = v1[1]; u1[2] = v1[2]; double projection12 = innerProduct(u1, v2)/innerProduct(u1, u1); double projection13 = innerProduct(u1, v3)/innerProduct(u1, u1); double u2[3]; u2[0] = v2[0]-projection12*u1[0]; u2[1] = v2[1]-projection12*u1[1]; u2[2] = v2[2]-projection12*u1[2]; double projection23 = innerProduct(u2, v3)/innerProduct(u2, u2); double u3[3]; u3[0] = v3[0]-projection13*u1[0]-projection23*u2[0]; u3[1] = v3[1]-projection13*u1[1]-projection23*u2[1]; u3[2] = v3[2]-projection13*u1[2]-projection23*u2[2]; vector<double> e1; e1.push_back(u1[0]/sqrt(innerProduct(u1,u1))); e1.push_back(u1[1]/sqrt(innerProduct(u1,u1))); e1.push_back(u1[2]/sqrt(innerProduct(u1,u1))); vector<double> e2; e2.push_back(u2[0]/sqrt(innerProduct(u2,u2))); e2.push_back(u2[1]/sqrt(innerProduct(u2,u2))); e2.push_back(u2[2]/sqrt(innerProduct(u2,u2))); vector<double> e3; e3.push_back(u3[0]/sqrt(innerProduct(u3,u3))); e3.push_back(u3[1]/sqrt(innerProduct(u3,u3))); e3.push_back(u3[2]/sqrt(innerProduct(u3,u3))); vector<vector<double>> orthonormalBasis; orthonormalBasis.push_back(e1); orthonormalBasis.push_back(e2); orthonormalBasis.push_back(e3); return orthonormalBasis; }
void findPoleAntiPole(int vsize) { tVertex site; double *pole_vector; double avg_normal[3] = { 0, }; facetT *neighbor, **neighborp; tVertex pole_voronoi_vertex = NULL; tVertex antipole_voronoi_vertex = NULL; vertexT *temp_voronoi_vertexT = NULL; tVertex temp_voronoi_vertex; tList site_voronoi_vertices; double temp_dist = 0; double max_dist = 0; int neighbor_size = 0; int i; tVertex temp_vertex; tVertex temp_vertices; int is_on_convexhull = 0; temp_vertex = vertices; temp_vertices = vertices; site = vertices; // for all vertices do { site_voronoi_vertices = site->vvlist; if (!site_voronoi_vertices) { temp_vertex = temp_vertex->next; site = site->next; continue; } temp_voronoi_vertexT = (vertexT*)site_voronoi_vertices->p; if (!temp_voronoi_vertexT) { // lies on the CH: compute the average of the outer nomals of the adjacents. pole_vector = (double *)calloc(3, sizeof(double)); neighbor_size = 0; FOREACHneighbor_(temp_voronoi_vertexT) { neighbor_size++; avg_normal[X] += neighbor->normal[X]; avg_normal[Y] += neighbor->normal[Y]; avg_normal[Z] += neighbor->normal[Z]; } avg_normal[X] /= neighbor_size; avg_normal[Y] /= neighbor_size; avg_normal[Z] /= neighbor_size; for (i = 0; i < 3; i++) { pole_vector[i] = avg_normal[i]; } is_on_convexhull = TRUE; } else { site_voronoi_vertices = site->vvlist; do { // Find the farthest Voronoi vertex from s. temp_voronoi_vertex = (tVertex)(site_voronoi_vertices->p); temp_dist = pointDist(site, temp_voronoi_vertex); if (temp_dist > max_dist) { pole_voronoi_vertex = temp_voronoi_vertex; max_dist = temp_dist; } } while (site_voronoi_vertices != site->vvlist); if (pole_voronoi_vertex){ if (max_dist > MAX_DIST) { pole_voronoi_vertex = NULL; } else { pole_voronoi_vertex->ispole = TRUE; pole_voronoi_vertex->vnum = vsize++; ADD(vertices, pole_voronoi_vertex); pole_vector = (double *)calloc(3, sizeof(double)); for (i = 0; i < 3; i++) { pole_vector[i] = pole_voronoi_vertex->v[i]; } } } } max_dist = 0; temp_dist = 0; // find a antipole site_voronoi_vertices = site->vvlist; if (pole_voronoi_vertex != NULL) { do { temp_voronoi_vertex = (tVertex)(site_voronoi_vertices->p); if (temp_voronoi_vertex->ispole) { continue; } temp_dist = innerProduct(site, pole_voronoi_vertex, temp_voronoi_vertex); if (temp_dist > max_dist) { antipole_voronoi_vertex = temp_voronoi_vertex; max_dist = temp_dist; } site_voronoi_vertices = site_voronoi_vertices->next; } while (site_voronoi_vertices != site->vvlist); } else if (is_on_convexhull) { // the site is on CH do { temp_voronoi_vertex = (tVertex)(site_voronoi_vertices->p); tVertex temp_vertex = MakeTempVertex(pole_vector); temp_dist = innerProduct(site, temp_vertex, temp_voronoi_vertex); if (temp_dist > max_dist) { antipole_voronoi_vertex = temp_voronoi_vertex; max_dist = temp_dist; } site_voronoi_vertices = site_voronoi_vertices->next; } while (site_voronoi_vertices != site->vvlist); } if (antipole_voronoi_vertex){ if (max_dist > MAX_DIST) { antipole_voronoi_vertex = NULL; } else { antipole_voronoi_vertex->ispole = TRUE; antipole_voronoi_vertex->vnum = vsize++; ADD(vertices, antipole_voronoi_vertex); } } max_dist = 0; avg_normal[0] = 0; avg_normal[1] = 0; avg_normal[2] = 0; pole_vector = NULL; pole_voronoi_vertex = NULL; antipole_voronoi_vertex = NULL; is_on_convexhull = FALSE; temp_vertex = temp_vertex->next; site = site->next; } while (temp_vertex != temp_vertices);
bool DGKTSD::cr(const DKTS& ai, const DKTS& xi) { bool value = true; DKTVector& w = attr_w(); DKTVector& r = attr_r(); DKTVector& x = attr_direction(); DKTVector& a = attr_ap(); DKTVector& aOld = attr_apo(); DKTVector& b = attr_b(); DKTVector& bOld = attr_bo(); DKTVector& p = attr_p(); DKTVector& pOld = attr_po(); DKTVector& grad = attr_gradientV(); //Init // r=grad - H*d evaluateHf(ai, xi, attr_direction, attr_r); r *= -1.0; r += grad; /* // po = 0 attr_po.setAllEntrysNull(); */ // p=W^-1*r evaluateAinv(attr_r, attr_p); // a = H*p evaluateHf(ai, xi, attr_p, attr_ap); // b = W^-1*ap evaluateAinv(attr_ap, attr_b); // w = A*b evaluateHf(ai, xi, attr_b, attr_w); LongReal eps = epsilonCR(); LongReal error = innerProduct(a, b); LongReal errorO = error; LongReal errorE = l2(r); LongReal lambda = 1.0, a0 = 1.0, a1 = 1.0; lambda = innerProduct(r, b)/error; a0 = innerProduct(w, b)/error; x.update( lambda, p); r.update(-lambda, a); bOld = p; p *= -a0; p.update(1.0, b); pOld = bOld; bOld = a; a *= -a0; a.update(1.0, w); aOld = bOld; bOld = b; evaluateAinv(attr_ap, attr_b); evaluateHf(ai, xi, attr_b, attr_w); errorO = error; error = innerProduct(a, b); const LongInt maxSteps = maxStepsCR(); LongInt numberOfIterations = 2; while(eps<errorE && numberOfIterations <= maxSteps) { lambda = innerProduct(r, b)/error; a0 = innerProduct(w, b)/error; a1 = innerProduct(w, bOld)/errorO; x.update( lambda, p); r.update(-lambda, a); bOld = p; p *= -a0; p.update(1.0, b); p.update(-a1, pOld); pOld = bOld; bOld = a; a *= -a0; a.update(1.0, w); a.update(-a1, aOld); aOld = bOld; bOld = b; evaluateAinv(attr_ap, attr_b); evaluateHf(ai, xi, attr_b, attr_w); errorO = error; error = innerProduct(a, b); errorE = l2(r); numberOfIterations++; } cout << "l2(p) = " << l2(p) << " " << l2(r); return value; }
void ISOP2P1::buildMatrix() { /// 计算一下各空间自由度和总自由度. int n_dof_v = fem_space_v.n_dof(); int n_dof_p = fem_space_p.n_dof(); int n_total_dof = 2 * n_dof_v + n_dof_p; if (n_total_dof != sp_stokes.n_rows()) { std::cerr << "ERROR: the demision of matrix is not correct!" << std::endl; exit(-1); } else std::cout << "dof no. of v: " << n_dof_v << ", " << "dof no. of p: " << n_dof_p << ", " << "total dof no.: " << n_total_dof << std::endl; /// 构建系数矩阵和右端项. mat_v_stiff.reinit(sp_vxvx); mat_v_mass.reinit(sp_vxvx); mat_pvx_divT.reinit(sp_pvx); mat_pvy_divT.reinit(sp_pvy); FEMSpace<double, DIM>::ElementIterator the_element_v = fem_space_v.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element_v = fem_space_v.endElement(); /// 遍历速度单元, 拼装相关系数矩阵和右端项. for (the_element_v = fem_space_v.beginElement(); the_element_v != end_element_v; ++the_element_v) { /// 当前单元信息. double volume = the_element_v->templateElement().volume(); /// 积分精度, u 和 p 都是 1 次, 梯度和散度 u 都是常数. 因此矩阵拼 /// 装时积分精度不用超过 1 次. (验证一下!) const QuadratureInfo<DIM>& quad_info = the_element_v->findQuadratureInfo(3); std::vector<double> jacobian = the_element_v->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<DIM> > q_point = the_element_v->local_to_global(quad_info.quadraturePoint()); /// 速度单元信息. std::vector<std::vector<std::vector<double> > > basis_gradient_v = the_element_v->basis_function_gradient(q_point); std::vector<std::vector<double> > basis_value_v = the_element_v->basis_function_value(q_point); const std::vector<int>& element_dof_v = the_element_v->dof(); int n_element_dof_v = the_element_v->n_dof(); // std::cout << the_element_v->index() << std::endl; /// 压力单元信息. Element<double, DIM> &p_element = fem_space_p.element(index_ele_v2p[the_element_v->index()]); const std::vector<int>& element_dof_p = p_element.dof(); std::vector<std::vector<double> > basis_value_p = p_element.basis_function_value(q_point); int n_element_dof_p = p_element.n_dof(); /// 实际拼装. for (int l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; for (int i = 0; i < n_element_dof_v; ++i) { for (int j = 0; j < n_element_dof_v; ++j) { double cont = Jxw * innerProduct(basis_gradient_v[i][l], basis_gradient_v[j][l]); /// V Stiff mat_v_stiff.add(element_dof_v[i], element_dof_v[j], cont); cont = Jxw * basis_value_v[i][l] * basis_value_v[j][l]; /// V Mass mat_v_mass.add(element_dof_v[i], element_dof_v[j], cont); } for (int j = 0; j < n_element_dof_p; ++j) { /// DivT x double cont = -Jxw * (basis_gradient_v[i][l][0] * basis_value_p[j][l]); mat_pvx_divT.add(element_dof_v[i], element_dof_p[j], cont); /// DivT y cont = -Jxw * (basis_gradient_v[i][l][1] * basis_value_p[j][l]); mat_pvy_divT.add(element_dof_v[i], element_dof_p[j], cont); } } } } /// 构建系数矩阵和右端项. mat_p_mass.reinit(sp_mass_p); mat_p_stiff.reinit(sp_mass_p); mat_vxp_div.reinit(sp_vxp); mat_vyp_div.reinit(sp_vyp); FEMSpace<double, DIM>::ElementIterator the_element_p = fem_space_p.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element_p = fem_space_p.endElement(); /// 遍历压力单元. 拼装矩阵和右端项. for (the_element_p = fem_space_p.beginElement(); the_element_p != end_element_p; ++the_element_p) { /// 当前单元信息. double volume_p = the_element_p->templateElement().volume(); const QuadratureInfo<DIM>& quad_info_p = the_element_p->findQuadratureInfo(3); std::vector<double> jacobian_p = the_element_p->local_to_global_jacobian(quad_info_p.quadraturePoint()); int n_quadrature_point = quad_info_p.n_quadraturePoint(); std::vector<Point<DIM> > q_point_p = the_element_p->local_to_global(quad_info_p.quadraturePoint()); /// 压力单元信息. std::vector<std::vector<double> > basis_value_p = the_element_p->basis_function_value(q_point_p); std::vector<std::vector<std::vector<double> > > basis_gradient_p = the_element_p->basis_function_gradient(q_point_p); const std::vector<int>& element_dof_p = the_element_p->dof(); int n_element_dof_p = the_element_p->n_dof(); for (int i = 0; i < n_element_dof_p; ++i) { for (int l = 0; l < n_quadrature_point; ++l) { for (int j = 0; j < n_element_dof_p; ++j) { double Jxw = quad_info_p.weight(l) * jacobian_p[l] * volume_p; double cont = Jxw * basis_value_p[i][l] * basis_value_p[j][l]; mat_p_mass.add(element_dof_p[i], element_dof_p[j], cont); /// mat_p_stiff. cont = Jxw * innerProduct(basis_gradient_p[i][l], basis_gradient_p[j][l]); mat_p_stiff.add(element_dof_p[i], element_dof_p[j], cont); } } int idx_p = the_element_p->index(); int n_chi = index_ele_p2v[idx_p].size(); for (int k = 0; k < n_chi; k++) { /// 速度单元信息. Element<double, DIM> &v_element = fem_space_v.element(index_ele_p2v[idx_p][k]); /// 几何信息. double volume = v_element.templateElement().volume(); const QuadratureInfo<DIM>& quad_info = v_element.findQuadratureInfo(3); std::vector<double> jacobian = v_element.local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<DIM> > q_point = v_element.local_to_global(quad_info.quadraturePoint()); const std::vector<int>& element_dof_v = v_element.dof(); std::vector<std::vector<std::vector<double> > > basis_gradient_v = v_element.basis_function_gradient(q_point); int n_element_dof_v = v_element.n_dof(); /// 压力单元信息. std::vector<std::vector<std::vector<double> > > basis_gradient_p = the_element_p->basis_function_gradient(q_point); std::vector<std::vector<double> > basis_value_p = the_element_p->basis_function_value(q_point); /// 具体拼装. for (int l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; for (int j = 0; j < n_element_dof_v; ++j) { /// Div x double cont = -Jxw * basis_value_p[i][l] * basis_gradient_v[j][l][0]; mat_vxp_div.add(element_dof_p[i], element_dof_v[j], cont); /// Div y cont = -Jxw * basis_value_p[i][l] * basis_gradient_v[j][l][1]; mat_vyp_div.add(element_dof_p[i], element_dof_v[j], cont); } } } } } // 输出测试矩阵, 只限小规模矩阵. // outputMat("Axx",mat_v_stiff); // outputMat("Mxx",mat_v_mass); // outputMat("Apx",mat_pvx_divT); // outputMat("Apy",mat_pvy_divT); // outputMat("Axp",mat_vxp_div); // outputMat("Ayp",mat_vyp_div); std::cout << "Basic matrixes builded." << std::endl; };
double Vector::sumSquares () const { return innerProduct( *this ); }
void ISOP2P1::solveNS(int method) { int n_dof_v = fem_space_v.n_dof(); int n_dof_p = fem_space_p.n_dof(); int n_total_dof = n_dof_v * 2 + n_dof_p; /// 开始迭代. double error_N = 1.0; int iteration_times = 0; while (error_N > n_tol) { /// Newton 迭代或 Picard 迭代. /// 先更新和速度场有关的矩阵块. updateNonlinearMatrix(); /// 构建迭代矩阵. if (method == 1) buildNewtonSys4NS(); else if (method == 2) buildPicardSys4NS(); else if (method == 3) if (iteration_times < 2) buildPicardSys4NS(); else buildNewtonSys4NS(); else { std::cout << "Newton: 1, Picard: 2, Hybrid: 3." << std::endl; exit(1); } /// 建立右端项. rhs.reinit(n_total_dof); FEMSpace<double, DIM>::ElementIterator the_element_v = fem_space_v.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element_v = fem_space_v.endElement(); FEMSpace<double, DIM>::ElementIterator the_element_p = fem_space_p.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element_p = fem_space_p.endElement(); /// 遍历速度单元, 拼装相关系数矩阵和右端项. for (the_element_v = fem_space_v.beginElement(); the_element_v != end_element_v; ++the_element_v) { /// 当前单元信息. double volume = the_element_v->templateElement().volume(); /// 积分精度, u 和 p 都是 1 次, 梯度和散度 u 都是常数. 因此矩阵拼 /// 装时积分精度不用超过 1 次. (验证一下!) const QuadratureInfo<DIM>& quad_info = the_element_v->findQuadratureInfo(4); std::vector<double> jacobian = the_element_v->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<DIM> > q_point = the_element_v->local_to_global(quad_info.quadraturePoint()); /// 速度单元信息. std::vector<std::vector<std::vector<double> > > basis_gradient_v = the_element_v->basis_function_gradient(q_point); std::vector<std::vector<double> > basis_value_v = the_element_v->basis_function_value(q_point); const std::vector<int>& element_dof_v = the_element_v->dof(); std::vector<double> fx_value = source_v[0].value(q_point, *the_element_v); std::vector<double> fy_value = source_v[1].value(q_point, *the_element_v); int n_element_dof_v = the_element_v->n_dof(); std::vector<double> vx_value = v_h[0].value(q_point, *the_element_v); std::vector<double> vy_value = v_h[1].value(q_point, *the_element_v); std::vector<std::vector<double> > vx_gradient = v_h[0].gradient(q_point, *the_element_v); std::vector<std::vector<double> > vy_gradient = v_h[1].gradient(q_point, *the_element_v); /// 压力单元信息. Element<double, DIM> &p_element = fem_space_p.element(index_ele_v2p[the_element_v->index()]); const std::vector<int>& element_dof_p = p_element.dof(); std::vector<std::vector<std::vector<double> > > basis_gradient_p = p_element.basis_function_gradient(q_point); std::vector<std::vector<double> > basis_value_p = p_element.basis_function_value(q_point); std::vector<double> p_value = p_h.value(q_point, p_element); int n_element_dof_p = p_element.n_dof(); /// 实际拼装. for (int l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; for (int i = 0; i < n_element_dof_v; ++i) { double rhs_cont = fx_value[l] * basis_value_v[i][l]; rhs_cont -= (vx_value[l] * vx_gradient[l][0] + vy_value[l] * vx_gradient[l][1]) * basis_value_v[i][l]; rhs_cont -= viscosity * innerProduct(basis_gradient_v[i][l], vx_gradient[l]); rhs_cont += p_value[l] * basis_gradient_v[i][l][0]; rhs_cont *= Jxw; rhs(element_dof_v[i]) += rhs_cont; rhs_cont = fy_value[l] * basis_value_v[i][l]; rhs_cont -= (vx_value[l] * vy_gradient[l][0] + vy_value[l] * vy_gradient[l][1]) * basis_value_v[i][l]; rhs_cont -= viscosity * innerProduct(basis_gradient_v[i][l], vy_gradient[l]); rhs_cont += p_value[l] * basis_gradient_v[i][l][1]; rhs_cont *= Jxw; rhs(n_dof_v + element_dof_v[i]) += rhs_cont; } } } /// 遍历压力单元. 拼装矩阵和右端项. for (the_element_p = fem_space_p.beginElement(); the_element_p != end_element_p; ++the_element_p) { const std::vector<int>& element_dof_p = the_element_p->dof(); int n_element_dof_p = the_element_p->n_dof(); for (int i = 0; i < n_element_dof_p; ++i) { int idx_p = the_element_p->index(); int n_chi = index_ele_p2v[idx_p].size(); for (int k = 0; k < n_chi; k++) { /// 速度单元信息. Element<double, DIM> &v_element = fem_space_v.element(index_ele_p2v[idx_p][k]); /// 几何信息. double volume = v_element.templateElement().volume(); const QuadratureInfo<DIM>& quad_info = v_element.findQuadratureInfo(4); std::vector<double> jacobian = v_element.local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<DIM> > q_point = v_element.local_to_global(quad_info.quadraturePoint()); std::vector<std::vector<double> > vx_gradient = v_h[0].gradient(q_point, v_element); std::vector<std::vector<double> > vy_gradient = v_h[1].gradient(q_point, v_element); std::vector<double> vx_value = v_h[0].value(q_point, v_element); std::vector<double> vy_value = v_h[1].value(q_point, v_element); /// 压力单元信息. std::vector<std::vector<double> > basis_value_p = the_element_p->basis_function_value(q_point); /// 具体拼装. for (int l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; /// 右端项还是零. 源项和 Neumann 条件. double rhs_cont = Jxw * basis_value_p[i][l] * (vx_gradient[l][0] + vy_gradient[l][1]); rhs(2 * n_dof_v + element_dof_p[i]) += rhs_cont; } } } } /// 初始化未知量. Vector<double> x(n_total_dof); /// 边界条件处理. boundaryValueNS(x); std::cout << "nonlinear res:" << std::endl; double revx = 0.0; for (int i = 0; i < n_dof_v; ++i) revx += rhs(i) * rhs(i); std::cout << "vx re: " << sqrt(revx) << std::endl; double revy = 0.0; for (int i = 0; i < n_dof_v; ++i) revy += rhs(i + n_dof_v) * rhs(i + n_dof_v); std::cout << "vy re: " << sqrt(revy) << std::endl; double rep = 0.0; for (int i = 0; i < n_dof_p; ++i) rep += rhs(i + 2 * n_dof_v) * rhs(i + 2 * n_dof_v); std::cout << "p re: " << sqrt(rep) << std::endl; double re = revx + revy +rep; std::cout << "total re: " << sqrt(re) << std::endl; std::cout << "pause ..." << std::endl; getchar(); if (sqrt(re) < n_tol) { std::cout << "Covergence with residual: " << sqrt(re) << " in step " << iteration_times << std::endl; break; } std::cout << "Building precondition matrix ..." << std::endl; /// 矩阵求解. SparseMatrix<double> mat_Axx(sp_vxvx); SparseMatrix<double> mat_Ayy(sp_vyvy); SparseMatrix<double> mat_Wxy(sp_vyvx); SparseMatrix<double> mat_Wyx(sp_vxvy); SparseMatrix<double> mat_BTx(sp_pvx); SparseMatrix<double> mat_BTy(sp_pvy); for (int i = 0; i < sp_vxvx.n_nonzero_elements(); ++i) mat_Axx.global_entry(i) = matrix.global_entry(index_vxvx[i]); for (int i = 0; i < sp_vyvy.n_nonzero_elements(); ++i) mat_Ayy.global_entry(i) = matrix.global_entry(index_vyvy[i]); for (int i = 0; i < sp_vyvx.n_nonzero_elements(); ++i) mat_Wxy.global_entry(i) = matrix.global_entry(index_vyvx[i]); for (int i = 0; i < sp_vxvy.n_nonzero_elements(); ++i) mat_Wyx.global_entry(i) = matrix.global_entry(index_vxvy[i]); for (int i = 0; i < sp_pvx.n_nonzero_elements(); ++i) mat_BTx.global_entry(i) = matrix.global_entry(index_pvx[i]); for (int i = 0; i < sp_pvy.n_nonzero_elements(); ++i) mat_BTy.global_entry(i) = matrix.global_entry(index_pvy[i]); std::cout << "Precondition matrix builded!" << std::endl; /// 矩阵求解. dealii::SolverControl solver_control (4000000, l_tol); SolverGMRES<Vector<double> >::AdditionalData para(2000, false, true); SolverGMRES<Vector<double> > gmres (solver_control, para); std::cout << "Begin to solve linear system ..." << std::endl; // gmres.solve (matrix, x, rhs, navierstokes_preconditioner); gmres.solve (matrix, x, rhs, PreconditionIdentity()); /// 调试块: 直接观测真实残量. // Vector<double> tmp(n_total_dof); // matrix.vmult(tmp, x); // tmp -= rhs; // std::cout << "linear residual: " << tmp.l2_norm() << std::endl; // getchar(); FEMFunction<double, DIM> res_vx(fem_space_v); FEMFunction<double, DIM> res_vy(fem_space_v); FEMFunction<double, DIM> res_p(fem_space_p); /// 更新数值解. for (int i = 0; i < n_dof_v; ++i) { v_h[0](i) += x(i); res_vx(i) = x(i); v_h[1](i) += x(i + n_dof_v); res_vy(i) = x(i+ n_dof_v); } for (int i = 0; i < n_dof_p; ++i) { p_h(i) += x(i + 2 * n_dof_v); res_p(i) = x(i + 2 * n_dof_v); } double r_vx = Functional::L2Norm(res_vx, 1); double r_vy = Functional::L2Norm(res_vy, 1); double r_p = Functional::L2Norm(res_p, 1); /// 这个其实是更新... error_N = r_vx + r_vy + r_p; std::cout.setf(std::ios::fixed); std::cout.precision(20); std::cout << "updated vx: " << r_vx << std::endl; std::cout << "updated vy: " << r_vy << std::endl; std::cout << "updated p: " << r_p << std::endl; std::cout << "total updated: " << error_N << std::endl; std::cout << "step " << iteration_times << ", total updated: " << error_N << ", GMRES stpes: " << solver_control.last_step() << std::endl; iteration_times++; if (iteration_times > 10) { std::cout << "Disconvergence at step 10." << std::endl; break; } } };
/** * Computes Gram matrix of a specified kernel. Given two sets of vectors * A (n1 vectors) and B (n2 vectors), it returns Gram matrix K (n1 x n2). * * @param kernelType 'linear' | 'poly' | 'rbf' | 'cosine' * * @param kernelParam -- | degree | sigma | -- * * @param A a 1D {@code Vector} array * * @param B a 1D {@code Vector} array * * @return Gram matrix (n1 x n2) */ Matrix& calcKernel(std::string kernelType, double kernelParam, Vector** A, int nA, Vector** B, int nB) { Matrix* K = null; if (kernelType == "linear") { double** resData = allocate2DArray(nA, nB, 0); double* resRow = null; Vector* V = null; for (int i = 0; i < nA; i++) { resRow = resData[i]; V = A[i]; for (int j = 0; j < nB; j++) { resRow[j] = innerProduct(*V, *B[j]); } } K = new DenseMatrix(resData, nA, nB); // K = A.transpose().mtimes(B); } else if (kernelType == "cosine") { double* AA = new double[nA]; Vector* V = null; for (int i = 0; i < nA; i++) { V = A[i]; // AA[i] = sum(V->times(*V)); AA[i] = innerProduct(*V, *V); } double* BB = new double[nB]; for (int i = 0; i < nB; i++) { V = B[i]; // BB[i] = sum(V->times(*V)); BB[i] = innerProduct(*V, *V); } double** resData = allocate2DArray(nA, nB, 0); double* resRow = null; for (int i = 0; i < nA; i++) { resRow = resData[i]; V = A[i]; for (int j = 0; j < nB; j++) { resRow[j] = innerProduct(*V, *B[j]) / sqrt(AA[i] * BB[j]); } } K = new DenseMatrix(resData, nA, nB); delete[] AA; delete[] BB; // K = dotMultiply(scalarDivide(1, sqrt(kron(AA.transpose(), BB))), AB); } else if (kernelType == "poly") { double** resData = allocate2DArray(nA, nB, 0); double* resRow = null; Vector* V = null; for (int i = 0; i < nA; i++) { resRow = resData[i]; V = A[i]; for (int j = 0; j < nB; j++) { resRow[j] = pow(innerProduct(*V, *B[j]), kernelParam); } } K = new DenseMatrix(resData, nA, nB); // K = pow(A.transpose().mtimes(B), kernelParam); } else if (kernelType == "rbf") { K = &l2DistanceSquare(A, nA, B, nB); timesAssign(*K, -1 / (2 * pow(kernelParam, 2))); expAssign(*K); // K = exp(l2DistanceSquare(X1, X2).times(-1 / (2 * Math.pow(kernelParam, 2)))); } return *K; }
bool DGKTSD::evaluateWHf(const DKTS& a, const DKTS& xi, const DKTS& v, DKTS& w) const { bool value = true; LongInt d = DGKTSD::d(); LongInt k = DGKTSD::k(); LongInt l = DGKTSD::l(); LongInt m = DGKTSD::m(); w.setNull(); attr_w().setNull(); for(LongInt mu1=0; mu1<d; mu1++) { for(LongInt j1=0; j1<k; j1++) { const LongReal& preFactor = W(j1, mu1); DKTVector& work_jmu = attr_w(j1, mu1); if(mu1!=0) { //The Matrix G const DKTVector& xjm = xi(j1, mu1); const DKTVector& vjm = v(j1, mu1); work_jmu.update(2.0*innerProduct(xjm, vjm), xjm); work_jmu.update((x(j1, j1, mu1) - 1.0), vjm); work_jmu *= 4.0*attr_lambda1*preFactor; } for(LongInt mu2=0; mu2<d; mu2++) { if(mu2!=mu1) { for(LongInt j2=0; j2<k; j2++) { //The Matrix C and lambda2*G2(C) if(j1==j2) { work_jmu.update((1.0+2.0*attr_lambda2)*psi(j1, j2, mu1, mu2)*innerProduct(xi(j1, mu2), v(j2, mu2))*W(j2, mu2), xi(j2, mu1)); /* // The Matrix B = x^mu1 * d_j1,mu1,mu2 * (x^mu2)^t LongReal& vjm = v(j1, mu2)(0); dgemv (&AMatrix::conjTrans, &m, &k, &const_eins, &xi(mu2)(0), &m, &vjm, &const_inc, &const_null, &attr_workK[0], &const_inc); for(LongInt j=0; j<k; j++) { attr_workK[j] *= psi(j1, j, mu1, mu2); } dgemv (&AMatrix::notConjTrans, &m, &k, &const_eins, &xi(mu1)(0), &m, &attr_workK[0], &const_inc, &const_eins, &work_jmu(0), &const_inc); // The Matrix D = a^mu1 * da_j1,mu1,mu2 * (a^mu2)^t dgemv (&AMatrix::conjTrans, &m, &l, &const_minus_eins, &a(mu2)(0), &m, &vjm, &const_inc, &const_null, &attr_workL[0], &const_inc); for(LongInt i=0; i<l; i++) { attr_workL[i] *= phi(j1, i, mu1, mu2); } dgemv (&AMatrix::notConjTrans, &m, &l, &const_eins, &a(mu1)(0), &m, &attr_workL[0], &const_inc, &const_eins, &work_jmu(0), &const_inc); */ } else { work_jmu.update(psi(j1, j2, mu1, mu2)*innerProduct(xi(j1, mu2), v(j2, mu2))*W(j2, mu2), xi(j2, mu1)); } } } } work_jmu.update(attr_lambda2*psi(j1, j1, mu1, mu1)*W(j1, mu1), v(j1, mu1)); work_jmu *= preFactor; }// End for(LongInt j1=0; j1<k; j1++) for(LongInt j11=0; j11<k; j11++) { DKTVector& w_jmu = w(j11, mu1); for(LongInt j2=0; j2<k; j2++) { w_jmu.update(A(j11, j2, mu1), attr_w(j2, mu1)); } }// End for(LongInt j11=0; j11<k; j1++) }// End for(LongInt mu1=0; mu1<d; mu1++) w() += v(); return value; }
bool DGKTSD::crA(const DKTS& ai, const DKTS& xi) { bool value = true; DKTVector& w = attr_bo(); DKTVector& r = attr_r(); DKTVector& x = attr_direction(); DKTVector& a = attr_ap(); DKTVector& c = attr_po(); DKTVector& b = attr_b(); DKTVector& p = attr_p(); DKTVector& grad = attr_gradientV(); //Init // r=grad - H*d evaluateHf(ai, xi, attr_direction, attr_r); r *= -1.0; r += grad; // p=W^-1*r evaluateAinv(attr_r, attr_p); // a = H*p evaluateHf(ai, xi, attr_p, attr_ap); // b = W^-1*ap evaluateAinv(attr_ap, attr_b); // w = p w = p; LongReal error = innerProduct(a, b); LongReal errorO = error; LongReal errorE = l2(r); LongReal eps = epsilonCR();//*errorE; LongReal lambda = 1.0, a0 = 1.0; const LongInt maxSteps = maxStepsCR(); LongInt numberOfIterations = 1; while(eps<errorE && numberOfIterations <= maxSteps) { lambda = innerProduct(r, b)/error; x.update( lambda, p); r.update(-lambda, a); w.update(-lambda, b); evaluateWHf(ai, xi, attr_b, attr_po); a0 = innerProduct(r, c)/error; p *= -a0; p.update(1.0, w); // a = H*p evaluateHf(ai, xi, attr_p, attr_ap); // b = W^-1*ap evaluateAinv(attr_ap, attr_b); errorO = error; error = innerProduct(a, b); errorE = l2(r); numberOfIterations++; } if(attr_printCout) { cout << "crItr = " << setw(4) << numberOfIterations-1 << " "; } /* if(maxSteps < numberOfIterations) { x = grad; } */ return value; }
OrthogonalProjections::OrthogonalProjections(const Matrix& originalVectors, Real multiplierCutoff, Real tolerance) : originalVectors_(originalVectors), multiplierCutoff_(multiplierCutoff), numberVectors_(originalVectors.rows()), dimension_(originalVectors.columns()), validVectors_(true,originalVectors.rows()), // opposite way round from vector constructor orthoNormalizedVectors_(originalVectors.rows(), originalVectors.columns()) { std::vector<Real> currentVector(dimension_); for (Size j=0; j < numberVectors_; ++j) { if (validVectors_[j]) { for (Size k=0; k< numberVectors_; ++k) // create an orthormal basis not containing j { for (Size m=0; m < dimension_; ++m) orthoNormalizedVectors_[k][m] = originalVectors_[k][m]; if ( k !=j && validVectors_[k]) { for (Size l=0; l < k; ++l) { if (validVectors_[l] && l !=j) { Real dotProduct = innerProduct(orthoNormalizedVectors_, k, orthoNormalizedVectors_,l); for (Size n=0; n < dimension_; ++n) orthoNormalizedVectors_[k][n] -= dotProduct*orthoNormalizedVectors_[l][n]; } } Real normBeforeScaling= norm(orthoNormalizedVectors_,k); if (normBeforeScaling < tolerance) { validVectors_[k] = false; } else { Real normBeforeScalingRecip = 1.0/normBeforeScaling; for (Size m=0; m < dimension_; ++m) orthoNormalizedVectors_[k][m] *= normBeforeScalingRecip; } // end of else (norm < tolerance) } // end of if k !=j && validVectors_[k]) }// end of for (Size k=0; k< numberVectors_; ++k) // we now have an o.n. basis for everything except j Real prevNormSquared = normSquared(originalVectors_, j); for (Size r=0; r < numberVectors_; ++r) if (validVectors_[r] && r != j) { Real dotProduct = innerProduct(orthoNormalizedVectors_, j, orthoNormalizedVectors_,r); for (Size s=0; s < dimension_; ++s) orthoNormalizedVectors_[j][s] -= dotProduct*orthoNormalizedVectors_[r][s]; } Real projectionOnOriginalDirection = innerProduct(originalVectors_,j,orthoNormalizedVectors_,j); Real sizeMultiplier = prevNormSquared/projectionOnOriginalDirection; if (std::fabs(sizeMultiplier) < multiplierCutoff_) { for (Size t=0; t < dimension_; ++t) currentVector[t] = orthoNormalizedVectors_[j][t]*sizeMultiplier; } else validVectors_[j] = false; } // end of if (validVectors_[j]) projectedVectors_.push_back(currentVector); } //end of j loop numberValidVectors_ =0; for (Size i=0; i < numberVectors_; ++i) numberValidVectors_ += validVectors_[i] ? 1 : 0; } // end of constructor
double Util::vectorLengthEuclid(Rcpp::NumericVector x) { double val = innerProduct(x,x); return sqrt(val); }
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int i, j, k, mc, offset, it, maxit = 0; double *A, *x, *r, *r_new, mu, *cd, *Atr_prev, *Av = NULL, *v = NULL, *prev_r = NULL, norml1 = 0; size_t *C = NULL, *level_sizes = NULL; double *WU, maxDelta = 0, tol, *Atr, coarseningRatio; Trace trace; size_t rowLen = mxGetN(prhs[0]); size_t colLen = mxGetM(prhs[0]); trace.idx = 1; A = mxGetPr(prhs[0]); x = mxGetPr(prhs[1]); r = mxGetPr(prhs[2]); mu = *mxGetPr(prhs[3]); maxit = (int)*mxGetPr(prhs[4]); tol = *mxGetPr(prhs[5]); coarseningRatio = *mxGetPr(prhs[6]); Atr_prev = mxGetPr(prhs[7]); // mu is sometimes called lambda // tol - accuracy. The algorithm stops when maximal CD update is below tol. // coarseningRatio - the ration that we reduce the dictionary at each level. generally 0.5. /*Allocate memory and assign output pointer*/ plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); plhs[1] = mxCreateDoubleMatrix(rowLen, 1, mxREAL); plhs[2] = mxCreateDoubleMatrix(rowLen, 1, mxREAL); plhs[3] = mxCreateDoubleMatrix(colLen, 1, mxREAL); plhs[4] = mxCreateDoubleMatrix(maxit * 2, 1, mxREAL); plhs[5] = mxCreateDoubleMatrix(maxit * 2, 1, mxREAL); plhs[6] = mxCreateDoubleMatrix(1, 1, mxREAL); /*Get a pointer to the data space in our newly allocated memory*/ WU = mxGetPr(plhs[0]); cd = mxGetPr(plhs[1]); Atr = mxGetPr(plhs[2]); r_new = mxGetPr(plhs[3]); trace.fx_trace = mxGetPr(plhs[4]); trace.time_trace = mxGetPr(plhs[5]); trace.time_trace[0] = clock(); C = (size_t *) malloc(sizeof(size_t) * rowLen); if (C == NULL) { mexPrintf("malloc failed: C\n"); goto out; } level_sizes = (size_t *) malloc(sizeof(size_t) * MAX_NUM_OF_LEVELS); if (level_sizes == NULL) { mexPrintf("malloc failed: level_sizes\n"); goto malloc_level_sizes_err; } v = (double *) malloc(sizeof(double) * rowLen); if (v == NULL) { mexPrintf("malloc failed: v\n"); goto malloc_v_err; } Av = (double *) malloc(sizeof(double) * colLen); if (Av == NULL) { mexPrintf("malloc failed: Av\n"); goto malloc_Av_err; } prev_r = (double *) malloc(sizeof(double) * colLen); if (prev_r == NULL) { mexPrintf("malloc failed: prev_r\n"); goto malloc_prev_r_err; } for (i = 0; i < colLen; i++) { r_new[i] = r[i]; prev_r[i] = r[i]; Atr[i] = Atr_prev[i]; Av[i] = 0; } for (i = 0; i < rowLen; i++) { cd[i] = x[i]; v[i] = 0; norml1 += fabs(x[i]); } trace.fx_trace[0] = 0.5 * innerProduct(r, r, colLen) + mu * norml1; mexPrintf("MLCD: %lf\n", trace.fx_trace[0]); for (it = 0; it < maxit; ++it) { maxDelta = MLCD(A, cd, v, Av, r_new, prev_r, Atr, C, rowLen, colLen, mu, tol, (size_t)(1 / coarseningRatio), level_sizes, &trace); norml1 = 0; for (i = 0; i < rowLen; i++) { norml1 += fabs(cd[i]); } trace.fx_trace[trace.idx] = 0.5 * innerProduct(r_new, r_new, colLen) + mu * norml1; trace.time_trace[trace.idx] = (clock() - trace.time_trace[0]) / CLOCKS_PER_SEC; trace.idx++; if (maxDelta < tol) { break; } } trace.time_trace[0] = 0; *mxGetPr(plhs[6]) = trace.idx; *WU = it + 1; // for (; it < maxit ; ++it) { // maxDelta = Debiasing(A, cd, Av, Atr, rowLen, colLen, mu); // if (maxDelta < 0.2*tol) { // break; // } // } free(prev_r); malloc_prev_r_err: free(Av); malloc_Av_err: free(v); malloc_v_err: free(level_sizes); malloc_level_sizes_err: free(C); out: return; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray* prhs[]) { clock_t t1 = clock(); double* C = mxGetPr(prhs[0]); // Constraint matrix int c = (int)(mxGetM(prhs[0])); // number of constraints double* X = mxGetPr(prhs[1]); // data points int npts = (int)(mxGetM(prhs[1])); // number of data points int d = (int)(mxGetN(prhs[1])); // number of data points double* G0 = mxGetPr(prhs[2]); // input kernel factor matrix int r = (int)(mxGetN(prhs[2])); // dimensionality of factor matrix double tol = (double)(*mxGetPr(prhs[3])); // tolerance double gamma = (double)(*mxGetPr(prhs[4])); // gamma int max_iters = (int)(*mxGetPr(prhs[5])); // maximum number of iterations int rank = (int)(*mxGetPr(prhs[6])); // rank of input kernel matrix // allocating memory // initialize the low rank matrix as I_{rxr} double* B = (double*)mxCalloc(r*r,sizeof(double)); int B_dim[2] = {r,r}; for(int i = 0;i<r; i++) B[i*r+i] = 1; double* bhat = (double*)mxCalloc(c,sizeof(double)); double* lambda = (double*)mxCalloc(c,sizeof(double)); double* lambdaold = (double*)mxCalloc(c,sizeof(double)); double* v = (double*)mxCalloc(r,sizeof(double)); double* w = (double*)mxCalloc(r,sizeof(double)); int v_dim[2] = {r,1}; memcpy(bhat,C+3*c,sizeof(double)*c); int delta,iter; int cnt = 0; double beta,conv; iter = 0; clock_t t3_temp, t4_temp; double t_chol = 0.0; double t_chol_update = 0.0; while(1) { int i1 = C[cnt]-1; int i2 = C[cnt+c]-1; memset(v,0.0,sizeof(double)*r); for(int i = 0; i < r; i++) v[i] = G0[i*npts + i1] - G0[i*npts + i2]; innerProduct(B,B_dim,v,v_dim,w); delta = C[cnt+2*c]; double p,alpha; innerProduct(w,v_dim,w,v_dim,&p); alpha = min(lambda[cnt],delta*gamma/(gamma + 1)*(1/p - 1/bhat[cnt])); lambdaold[cnt] = lambda[cnt]; beta = delta*alpha/(1-delta*alpha*p); bhat[cnt] = gamma*bhat[cnt]/(gamma + delta*alpha*bhat[cnt]); lambda[cnt] = lambda[cnt] - alpha; t3_temp = clock(); t_chol_update += cholUpdateMult(beta,w,B,r); t4_temp = clock(); t_chol += ((double)(t4_temp-t3_temp)/((double)(CLOCKS_PER_SEC))); //for(int row_i = 0; row_i < r; row_i++) //{ // mexPrintf("\n"); // for(int col_i = 0;col_i < r;col_i++) // { // mexPrintf("%.2f ",B[col_i*r+row_i]); // } //} if(cnt == c-1) { double norm_sum, norm_lambda, norm_lambdaold, norm_lambdadiff; matrixMultiply(lambda,lambda,&norm_lambda,1,c,1); matrixMultiply(lambdaold,lambdaold,&norm_lambdaold,1,c,1); norm_lambda = sqrt(norm_lambda); norm_lambdaold = sqrt(norm_lambdaold); double normsum = norm_lambda + norm_lambdaold; if(normsum == 0) break; else { norm_lambdadiff = 0.0; for(int j = 0; j < c; j++) norm_lambdadiff += fabs(lambdaold[j] - lambda[j]); conv = norm_lambdadiff/normsum; if(conv < tol || iter >= max_iters) break; } } cnt = cnt % (c-1) + 1; iter++; if(iter % max(25000,c) == 0) { mexPrintf("itml iter: %d of %d, conv = %0.12f\n", iter, max_iters, conv); mexEvalString("drawnow;"); } } mexPrintf("itml converged to tol: %f, iter: %d\n", conv, iter); clock_t t2 = clock(); mexPrintf("total time taken in C++ = %.4lf\n", ((double)(t2-t1)/((double)(CLOCKS_PER_SEC)))); // mexPrintf("total time taken in chol update = %.4lf, %.4lf\n", t_chol,t_chol_update); mxArray* G = mxCreateDoubleMatrix(npts,r,mxREAL); matrixMultiply(G0,B,mxGetPr(G),npts,r,r); mxArray* mxbhat = mxCreateDoubleMatrix((mwSize)c,1,mxREAL); memcpy(mxGetPr(mxbhat),bhat,c*sizeof(double)); plhs[0] = G; plhs[1] = mxbhat; mxFree(B); mxFree(bhat); mxFree(lambda); mxFree(lambdaold); mxFree(v); }
double NOX::Epetra::Vector::innerProduct(const NOX::Abstract::Vector& y) const { return innerProduct(dynamic_cast<const NOX::Epetra::Vector&>(y)); }
int main(int argc, char * argv[]) { typedef MPI::HGeometryForest<DIM,DOW> forest_t; typedef MPI::BirdView<forest_t> ir_mesh_t; typedef FEMSpace<double,DIM,DOW> fe_space_t; typedef MPI::DOF::GlobalIndex<forest_t, fe_space_t> global_index_t; MPI_Init(&argc, &argv); forest_t forest(MPI_COMM_WORLD); ir_mesh_t ir_mesh; MPI::load_mesh(argv[1], forest, ir_mesh); /// 从一个目录中读入网格数据 int round = 0; if (argc >= 3) round = atoi(argv[2]); ir_mesh.globalRefine(round); ir_mesh.semiregularize(); ir_mesh.regularize(false); TemplateGeometry<DIM> tri; tri.readData("triangle.tmp_geo"); CoordTransform<DIM,DIM> tri_ct; tri_ct.readData("triangle.crd_trs"); TemplateDOF<DIM> tri_td(tri); tri_td.readData("triangle.1.tmp_dof"); BasisFunctionAdmin<double,DIM,DIM> tri_bf(tri_td); tri_bf.readData("triangle.1.bas_fun"); std::vector<TemplateElement<double,DIM,DIM> > tmp_ele(1); tmp_ele[0].reinit(tri, tri_td, tri_ct, tri_bf); RegularMesh<DIM,DOW>& mesh = ir_mesh.regularMesh(); fe_space_t fem_space(mesh, tmp_ele); u_int n_ele = mesh.n_geometry(DIM); fem_space.element().resize(n_ele); for (int i = 0;i < n_ele;i ++) { fem_space.element(i).reinit(fem_space, i, 0); } fem_space.buildElement(); fem_space.buildDof(); fem_space.buildDofBoundaryMark(); std::cout << "Building global indices ... " << std::flush; global_index_t global_index(forest, fem_space); global_index.build(); std::cout << "OK!" << std::endl; Epetra_MpiComm comm(forest.communicator()); Epetra_Map map(global_index.n_global_dof(), global_index.n_primary_dof(), 0, comm); global_index.build_epetra_map(map); /// 构造 Epetra 的分布式稀疏矩阵模板 std::cout << "Build sparsity pattern ... " << std::flush; Epetra_FECrsGraph G(Copy, map, 10); fe_space_t::ElementIterator the_ele = fem_space.beginElement(), end_ele = fem_space.endElement(); for (;the_ele != end_ele;++ the_ele) { const std::vector<int>& ele_dof = the_ele->dof(); u_int n_ele_dof = ele_dof.size(); /** * 建立从局部自由度数组到全局自由度数组的映射表,这是实现分布式并行 * 状态下的数据结构的关键一步。 */ std::vector<int> indices(n_ele_dof); for (u_int i = 0;i < n_ele_dof;++ i) { indices[i] = global_index(ele_dof[i]); } G.InsertGlobalIndices(n_ele_dof, &indices[0], n_ele_dof, &indices[0]); } G.GlobalAssemble(); std::cout << "OK!" << std::endl; /// 准备构造 Epetra 的分布式稀疏矩阵和计算分布式右端项 std::cout << "Build sparse matrix ... " << std::flush; Epetra_FECrsMatrix A(Copy, G); Epetra_FEVector b(map); the_ele = fem_space.beginElement(); for (;the_ele != end_ele;++ the_ele) { double vol = the_ele->templateElement().volume(); const QuadratureInfo<DIM>& qi = the_ele->findQuadratureInfo(5); std::vector<Point<DIM> > q_pnt = the_ele->local_to_global(qi.quadraturePoint()); int n_q_pnt = qi.n_quadraturePoint(); std::vector<double> jac = the_ele->local_to_global_jacobian(qi.quadraturePoint()); std::vector<std::vector<double> > bas_val = the_ele->basis_function_value(q_pnt); std::vector<std::vector<std::vector<double> > > bas_grad = the_ele->basis_function_gradient(q_pnt); const std::vector<int>& ele_dof = the_ele->dof(); u_int n_ele_dof = ele_dof.size(); FullMatrix<double> ele_mat(n_ele_dof, n_ele_dof); Vector<double> ele_rhs(n_ele_dof); for (u_int l = 0;l < n_q_pnt;++ l) { double JxW = vol*jac[l]*qi.weight(l); double f_val = _f_(q_pnt[l]); for (u_int i = 0;i < n_ele_dof;++ i) { for (u_int j = 0;j < n_ele_dof;++ j) { ele_mat(i, j) += JxW*(bas_val[i][l]*bas_val[j][l] + innerProduct(bas_grad[i][l], bas_grad[j][l])); } ele_rhs(i) += JxW*f_val*bas_val[i][l]; } } /** * 此处将单元矩阵和单元载荷先计算好,然后向全局的矩阵和载荷向量上 * 集中,可以提高效率。 */ std::vector<int> indices(n_ele_dof); for (u_int i = 0;i < n_ele_dof;++ i) { indices[i] = global_index(ele_dof[i]); } A.SumIntoGlobalValues(n_ele_dof, &indices[0], n_ele_dof, &indices[0], &ele_mat(0,0)); b.SumIntoGlobalValues(n_ele_dof, &indices[0], &ele_rhs(0)); } A.GlobalAssemble(); b.GlobalAssemble(); std::cout << "OK!" << std::endl; /// 准备解向量。 Epetra_Vector x(map); /// 调用 AztecOO 的求解器。 std::cout << "Solving the linear system ..." << std::flush; Epetra_LinearProblem problem(&A, &x, &b); AztecOO solver(problem); ML_Epetra::MultiLevelPreconditioner precond(A, true); solver.SetPrecOperator(&precond); solver.SetAztecOption(AZ_solver, AZ_cg); solver.SetAztecOption(AZ_output, 100); solver.Iterate(5000, 1.0e-12); std::cout << "OK!" << std::endl; Epetra_Map fe_map(-1, global_index.n_local_dof(), &global_index(0), 0, comm); FEMFunction<double,DIM> u_h(fem_space); Epetra_Import importer(fe_map, map); Epetra_Vector X(View, fe_map, &u_h(0)); X.Import(x, importer, Add); char filename[1024]; sprintf(filename, "u_h%d.dx", forest.rank()); u_h.writeOpenDXData(filename); MPI_Finalize(); return 0; }
void testFileInnerProduct(){ printf("\nTest file inner product:\n"); FILE *fr; const int maxLineLength = 20000; char line[maxLineLength]; int totalTests = 0, successTests = 0; time_t start_t, end_t; double diff_t; time(&start_t); fr = fopen("tests/tests-c/innerProductTests.txt", "rt"); while(1){ struct StabilizerState state1; struct StabilizerState state2; int eps, outEps, p, outP, m, outM; gsl_complex ans; //populate state1: //read n if(!readInt(fr, line, maxLineLength, &state1.n)){ break; } //read k if(!readInt(fr, line, maxLineLength, &state1.k)){ break; } //read Q if(!readInt(fr, line, maxLineLength, &state1.Q)){ break; } //read h double vectorDatah1[state1.n]; if(!readArray(fr, line, maxLineLength, vectorDatah1)){ break; } gsl_vector_view vectorViewh1 = gsl_vector_view_array(vectorDatah1, state1.n); state1.h = &vectorViewh1.vector; //read D double vectorDataD1[state1.n]; if(!readArray(fr, line, maxLineLength, vectorDataD1)){ break; } gsl_vector_view vectorViewD1 = gsl_vector_view_array(vectorDataD1, state1.n); state1.D = &vectorViewD1.vector; //read G double matrixDataG1[state1.n*state1.n]; if(!readArray(fr, line, maxLineLength, matrixDataG1)){ break; } gsl_matrix_view matrixViewG1 = gsl_matrix_view_array(matrixDataG1, state1.n, state1.n); state1.G = &matrixViewG1.matrix; //read Gbar double matrixDataGbar1[state1.n*state1.n]; if(!readArray(fr, line, maxLineLength, matrixDataGbar1)){ break; } gsl_matrix_view matrixViewGbar1 = gsl_matrix_view_array(matrixDataGbar1, state1.n, state1.n); state1.Gbar = &matrixViewGbar1.matrix; //read J double matrixDataJ1[state1.n*state1.n]; if(!readArray(fr, line, maxLineLength, matrixDataJ1)){ break; } gsl_matrix_view matrixViewJ1 = gsl_matrix_view_array(matrixDataJ1, state1.n, state1.n); state1.J = &matrixViewJ1.matrix; //populate state2: //read n if(!readInt(fr, line, maxLineLength, &state2.n)){ break; } //read k if(!readInt(fr, line, maxLineLength, &state2.k)){ break; } //read Q if(!readInt(fr, line, maxLineLength, &state2.Q)){ break; } //read h double vectorDatah2[state2.n]; if(!readArray(fr, line, maxLineLength, vectorDatah2)){ break; } gsl_vector_view vectorViewh2 = gsl_vector_view_array(vectorDatah2, state2.n); state2.h = &vectorViewh2.vector; //read D double vectorDataD2[state2.n]; if(!readArray(fr, line, maxLineLength, vectorDataD2)){ break; } gsl_vector_view vectorViewD2 = gsl_vector_view_array(vectorDataD2, state2.n); state2.D = &vectorViewD2.vector; //read G double matrixDataG2[state2.n*state2.n]; if(!readArray(fr, line, maxLineLength, matrixDataG2)){ break; } gsl_matrix_view matrixViewG2 = gsl_matrix_view_array(matrixDataG2, state2.n, state2.n); state2.G = &matrixViewG2.matrix; //read Gbar double matrixDataGbar2[state2.n*state2.n]; if(!readArray(fr, line, maxLineLength, matrixDataGbar2)){ break; } gsl_matrix_view matrixViewGbar2 = gsl_matrix_view_array(matrixDataGbar2, state2.n, state2.n); state2.Gbar = &matrixViewGbar2.matrix; //read J double matrixDataJ2[state2.n*state2.n]; if(!readArray(fr, line, maxLineLength, matrixDataJ2)){ break; } gsl_matrix_view matrixViewJ2 = gsl_matrix_view_array(matrixDataJ2, state2.n, state2.n); state2.J = &matrixViewJ2.matrix; //read outEps if(!readInt(fr, line, maxLineLength, &outEps)){ break; } //read outP if(!readInt(fr, line, maxLineLength, &outP)){ break; } //read outM if(!readInt(fr, line, maxLineLength, &outM)){ break; } innerProduct(&state1, &state2, &eps, &p, &m, &ans, 1); int isEpsWorking = eps == outEps ? 1 : 0; int isPWorking = p == outP ? 1 : 0; int isMWorking = mod(m, 8) == mod(outM, 8) ? 1 : 0; totalTests++; if((eps==0&&isEpsWorking) || isEpsWorking*isPWorking*isMWorking > 0){ successTests++; } else{ printf("eps: %d, outEps: %d, p: %d, outP: %d, m: %d, outM: %d", eps, outEps, p, outP, m, outM); printf("Test number %d failed.\n", totalTests); } /* if (totalTests == 100) { break; }*/ } fclose(fr); printf("%d out of %d tests successful.\n", successTests, totalTests); time(&end_t); diff_t = difftime(end_t, start_t); printf("Time elapsed: %f s\n", diff_t); printf("----------------------\n"); }
void ISOP2P1::computeMonitor() { if (isMoving == 0) { /// 将速度有限元空间的数值解插值到压力有限元空间中, /// 为了方便计算压力网格单元上的monitor的值. FEMFunction<double, DIM> _u_h(fem_space_p); FEMFunction<double, DIM> _v_h(fem_space_p); Operator::L2Interpolate(v_h[0], _u_h); Operator::L2Interpolate(v_h[1], _v_h); RegularMesh<DIM> &mesh_p = irregular_mesh_p->regularMesh(); int n_ele = mesh_p.n_geometry(DIM); Monitor.resize(n_ele, 0.0); /// 选取速度数值解的梯度做monitor, 跟文章中的monitor一致. FEMSpace<double, DIM>::ElementIterator the_element = fem_space_p.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element = fem_space_p.endElement(); for(; the_element != end_element; ++the_element) { double volume = the_element->templateElement().volume(); const QuadratureInfo<DIM> &quad_info = the_element->findQuadratureInfo(3); std::vector<double> jacobian = the_element->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<DIM> > q_point = the_element->local_to_global(quad_info.quadraturePoint()); std::vector<std::vector<double> > basis_value = the_element->basis_function_value(q_point); std::vector<double> u_h_value = _u_h.value(q_point, *the_element); std::vector<double> v_h_value = _v_h.value(q_point, *the_element); std::vector<std::vector<double> > u_h_gradient = _u_h.gradient(q_point, *the_element); std::vector<std::vector<double> > v_h_gradient = _v_h.gradient(q_point, *the_element); float d = 0.0, area = 0.0, cont = 0.0; for(int l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; area += Jxw; d += Jxw * (innerProduct(u_h_gradient[l], u_h_gradient[l]) + innerProduct(v_h_gradient[l], v_h_gradient[l])); } Monitor[the_element->index()] = d / area; } for (int i = 0; i < n_ele; ++i) Monitor[i] = sqrt(1.0 + alpha * pow(Monitor[i], beta)); /* 后验误差做monitor。 std::vector<double> side_length(n_face); std::vector<bool> flag(n_face, false); std::vector<double> jump_ux(n_face); std::vector<double> jump_uy(n_face); FEMSpace<double,DIM>::ElementIterator the_element_p = fem_space_p.beginElement(); FEMSpace<double,DIM>::ElementIterator end_element_p = fem_space_p.endElement(); /// 遍历所有速度单元,计算每条边上的 jump / ||v||_L2. for (; the_element_p != end_element_p; ++the_element_p) { /// 几何信息. double volume = the_element_p->templateElement().volume(); const QuadratureInfo<2>& quad_info = the_element_p->findQuadratureInfo(4); std::vector<double> jacobian = the_element_p->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<Point<2> > q_point = the_element_p->local_to_global(quad_info.quadraturePoint()); const GeometryBM& geometry = the_element_p->geometry(); for (int i = 0; i < geometry.n_boundary(); ++i) { int j = geometry.boundary(i); const GeometryBM& side = mesh_p.geometry(1, j); const Point<DIM>& p0 = mesh_p.point(mesh_p.geometry(0, side.boundary(0)).vertex(0)); const Point<DIM>& p1 = mesh_p.point(mesh_p.geometry(0, side.boundary(1)).vertex(0)); std::vector<double> vx_gradient = _u_h.gradient(midpoint(p0, p1), *the_element_p); std::vector<double> vy_gradient = _v_h.gradient(midpoint(p0, p1), *the_element_p); double vx_value = _u_h.value(midpoint(p0, p1), *the_element_p); double vy_value = _v_h.value(midpoint(p0, p1), *the_element_p); double v_L2norm = sqrt(vx_value * vx_value + vy_value * vy_value + eps); side_length[j] = distance(p0, p1); if (flag[j]) { jump_ux[j] -= (vx_gradient[0] * (p0[1] - p1[1]) + vx_gradient[1] * (p1[0] - p0[0])); jump_uy[j] -= (vy_gradient[0] * (p0[1] - p1[1]) + vy_gradient[1] * (p1[0] - p0[0])); flag[j] = false; } else { jump_ux[j] = (vx_gradient[0] * (p0[1] - p1[1]) + vx_gradient[1] * (p1[0] - p0[0])); jump_uy[j] = (vy_gradient[0] * (p0[1] - p1[1]) + vy_gradient[1] * (p1[0] - p0[0])); flag[j] = true; } } } the_element_p = fem_space_p.beginElement(); for(int i = 0; the_element_p != end_element_p; ++the_element_p, ++i) { const GeometryBM &geometry = the_element_p->geometry(); double cont = 0.0, total_ele_side_length = 0.0; for (int l = 0; l < geometry.n_boundary(); ++l) { int j = geometry.boundary(l); /// 如果编号是j的边是边界. if (flag[j]) continue; /// 将DIM个梯度沿法向方向上的跳跃平方值累加. cont += (jump_ux[j] * jump_ux[j] + jump_uy[j] * jump_uy[j]) * side_length[j]; total_ele_side_length += side_length[j]; } Monitor[i] = sqrt(cont / total_ele_side_length); } // for (int i = 0; i < n_geometry(DIM); ++i) // monitor(i) = 1.0 / sqrt(1.0 + alpha * pow(monitor(i) / max_monitor, 2)); */ } }