/** * Assemble the system matrix and right-hand side vector. */ void assemble() { const MeshBase& mesh = es.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); LinearImplicitSystem& system = es.get_system<LinearImplicitSystem>("Elasticity"); const unsigned int u_var = system.variable_number ("u"); const DofMap& dof_map = system.get_dof_map(); FEType fe_type = dof_map.variable_type(u_var); UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); QGauss qrule (dim, fe_type.default_quadrature_order()); fe->attach_quadrature_rule (&qrule); UniquePtr<FEBase> fe_face (FEBase::build(dim, fe_type)); QGauss qface(dim-1, fe_type.default_quadrature_order()); fe_face->attach_quadrature_rule (&qface); const std::vector<Real>& JxW = fe->get_JxW(); const std::vector<std::vector<Real> >& phi = fe->get_phi(); const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); DenseMatrix<Number> Ke; DenseSubMatrix<Number> Ke_var[3][3] = { {DenseSubMatrix<Number>(Ke), DenseSubMatrix<Number>(Ke), DenseSubMatrix<Number>(Ke)}, {DenseSubMatrix<Number>(Ke), DenseSubMatrix<Number>(Ke), DenseSubMatrix<Number>(Ke)}, {DenseSubMatrix<Number>(Ke), DenseSubMatrix<Number>(Ke), DenseSubMatrix<Number>(Ke)} }; DenseVector<Number> Fe; DenseSubVector<Number> Fe_var[3] = {DenseSubVector<Number>(Fe), DenseSubVector<Number>(Fe), DenseSubVector<Number>(Fe)}; std::vector<dof_id_type> dof_indices; std::vector< std::vector<dof_id_type> > dof_indices_var(3); MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { const Elem* elem = *el; dof_map.dof_indices (elem, dof_indices); for(unsigned int var=0; var<3; var++) { dof_map.dof_indices (elem, dof_indices_var[var], var); } const unsigned int n_dofs = dof_indices.size(); const unsigned int n_var_dofs = dof_indices_var[0].size(); fe->reinit (elem); Ke.resize (n_dofs,n_dofs); for(unsigned int var_i=0; var_i<3; var_i++) for(unsigned int var_j=0; var_j<3; var_j++) { Ke_var[var_i][var_j].reposition (var_i*n_var_dofs, var_j*n_var_dofs, n_var_dofs, n_var_dofs); } Fe.resize (n_dofs); for(unsigned int var=0; var<3; var++) { Fe_var[var].reposition (var*n_var_dofs, n_var_dofs); } for (unsigned int qp=0; qp<qrule.n_points(); qp++) { // assemble \int_Omega C_ijkl u_k,l v_i,j \dx for (unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++) for (unsigned int dof_j=0; dof_j<n_var_dofs; dof_j++) { for(unsigned int i=0; i<3; i++) for(unsigned int j=0; j<3; j++) for(unsigned int k=0; k<3; k++) for(unsigned int l=0; l<3; l++) { Ke_var[i][k](dof_i,dof_j) += JxW[qp] * elasticity_tensor(i,j,k,l) * dphi[dof_j][qp](l) * dphi[dof_i][qp](j); } } // assemble \int_Omega f_i v_i \dx DenseVector<Number> f_vec(3); f_vec(0) = 0.; f_vec(1) = 0.; f_vec(2) = -1.; for (unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++) { for(unsigned int i=0; i<3; i++) { Fe_var[i](dof_i) += JxW[qp] * ( f_vec(i) * phi[dof_i][qp] ); } } } // assemble \int_\Gamma g_i v_i \ds DenseVector<Number> g_vec(3); g_vec(0) = 0.; g_vec(1) = 0.; g_vec(2) = -1.; { for (unsigned int side=0; side<elem->n_sides(); side++) if (elem->neighbor(side) == NULL) { const std::vector<std::vector<Real> >& phi_face = fe_face->get_phi(); const std::vector<Real>& JxW_face = fe_face->get_JxW(); fe_face->reinit(elem, side); for (unsigned int qp=0; qp<qface.n_points(); qp++) { // Apply a traction if( mesh.get_boundary_info().has_boundary_id (elem, side, BOUNDARY_ID_MAX_X) ) { for (unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++) { for(unsigned int i=0; i<3; i++) { Fe_var[i](dof_i) += JxW_face[qp] * ( g_vec(i) * phi_face[dof_i][qp] ); } } } } } } dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); system.matrix->add_matrix (Ke, dof_indices); system.rhs->add_vector (Fe, dof_indices); } }
void InitialCondition::compute() { // -- NOTE ---- // The following code is a copy from libMesh project_vector.C plus it adds some features, so we can couple variable values // and we also do not call any callbacks, but we use our initial condition system directly. // ------------ // The element matrix and RHS for projections. // Note that Ke is always real-valued, whereas Fe may be complex valued if complex number support is enabled DenseMatrix<Real> Ke; DenseVector<Number> Fe; // The new element coefficients DenseVector<Number> Ue; const FEType & fe_type = _var.feType(); // The dimension of the current element const unsigned int dim = _current_elem->dim(); // The element type const ElemType elem_type = _current_elem->type(); // The number of nodes on the new element const unsigned int n_nodes = _current_elem->n_nodes(); // The global DOF indices std::vector<dof_id_type> dof_indices; // Side/edge DOF indices std::vector<unsigned int> side_dofs; // Get FE objects of the appropriate type // We cannot use the FE object in Assembly, since the following code is messing with the quadrature rules // for projections and would screw it up. However, if we implement projections from one mesh to another, // this code should use that implementation. UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); // Prepare variables for projection UniquePtr<QBase> qrule (fe_type.default_quadrature_rule(dim)); UniquePtr<QBase> qedgerule (fe_type.default_quadrature_rule(1)); UniquePtr<QBase> qsiderule (fe_type.default_quadrature_rule(dim-1)); // The values of the shape functions at the quadrature points const std::vector<std::vector<Real> > & phi = fe->get_phi(); // The gradients of the shape functions at the quadrature points on the child element. const std::vector<std::vector<RealGradient> > * dphi = NULL; const FEContinuity cont = fe->get_continuity(); if (cont == C_ONE) { const std::vector<std::vector<RealGradient> > & ref_dphi = fe->get_dphi(); dphi = &ref_dphi; } // The Jacobian * quadrature weight at the quadrature points const std::vector<Real> & JxW = fe->get_JxW(); // The XYZ locations of the quadrature points const std::vector<Point>& xyz_values = fe->get_xyz(); // Update the DOF indices for this element based on the current mesh _var.prepareIC(); dof_indices = _var.dofIndices(); // The number of DOFs on the element const unsigned int n_dofs = dof_indices.size(); if (n_dofs == 0) return; // Fixed vs. free DoFs on edge/face projections std::vector<char> dof_is_fixed(n_dofs, false); // bools std::vector<int> free_dof(n_dofs, 0); // Zero the interpolated values Ue.resize (n_dofs); Ue.zero(); // In general, we need a series of // projections to ensure a unique and continuous // solution. We start by interpolating nodes, then // hold those fixed and project edges, then // hold those fixed and project faces, then // hold those fixed and project interiors _fe_problem.sizeZeroes(n_nodes, _tid); // Interpolate node values first unsigned int current_dof = 0; for (unsigned int n = 0; n != n_nodes; ++n) { // FIXME: this should go through the DofMap, // not duplicate dof_indices code badly! const unsigned int nc = FEInterface::n_dofs_at_node (dim, fe_type, elem_type, n); if (!_current_elem->is_vertex(n)) { current_dof += nc; continue; } if (cont == DISCONTINUOUS) { libmesh_assert(nc == 0); } // Assume that C_ZERO elements have a single nodal // value shape function else if (cont == C_ZERO) { libmesh_assert(nc == 1); _qp = n; _current_node = _current_elem->get_node(n); Ue(current_dof) = value(*_current_node); dof_is_fixed[current_dof] = true; current_dof++; } // The hermite element vertex shape functions are weird else if (fe_type.family == HERMITE) { _qp = n; _current_node = _current_elem->get_node(n); Ue(current_dof) = value(*_current_node); dof_is_fixed[current_dof] = true; current_dof++; Gradient grad = gradient(*_current_node); // x derivative Ue(current_dof) = grad(0); dof_is_fixed[current_dof] = true; current_dof++; if (dim > 1) { // We'll finite difference mixed derivatives Point nxminus = _current_elem->point(n), nxplus = _current_elem->point(n); nxminus(0) -= TOLERANCE; nxplus(0) += TOLERANCE; Gradient gxminus = gradient(nxminus); Gradient gxplus = gradient(nxplus); // y derivative Ue(current_dof) = grad(1); dof_is_fixed[current_dof] = true; current_dof++; // xy derivative Ue(current_dof) = (gxplus(1) - gxminus(1)) / 2. / TOLERANCE; dof_is_fixed[current_dof] = true; current_dof++; if (dim > 2) { // z derivative Ue(current_dof) = grad(2); dof_is_fixed[current_dof] = true; current_dof++; // xz derivative Ue(current_dof) = (gxplus(2) - gxminus(2)) / 2. / TOLERANCE; dof_is_fixed[current_dof] = true; current_dof++; // We need new points for yz Point nyminus = _current_elem->point(n), nyplus = _current_elem->point(n); nyminus(1) -= TOLERANCE; nyplus(1) += TOLERANCE; Gradient gyminus = gradient(nyminus); Gradient gyplus = gradient(nyplus); // xz derivative Ue(current_dof) = (gyplus(2) - gyminus(2)) / 2. / TOLERANCE; dof_is_fixed[current_dof] = true; current_dof++; // Getting a 2nd order xyz is more tedious Point nxmym = _current_elem->point(n), nxmyp = _current_elem->point(n), nxpym = _current_elem->point(n), nxpyp = _current_elem->point(n); nxmym(0) -= TOLERANCE; nxmym(1) -= TOLERANCE; nxmyp(0) -= TOLERANCE; nxmyp(1) += TOLERANCE; nxpym(0) += TOLERANCE; nxpym(1) -= TOLERANCE; nxpyp(0) += TOLERANCE; nxpyp(1) += TOLERANCE; Gradient gxmym = gradient(nxmym); Gradient gxmyp = gradient(nxmyp); Gradient gxpym = gradient(nxpym); Gradient gxpyp = gradient(nxpyp); Number gxzplus = (gxpyp(2) - gxmyp(2)) / 2. / TOLERANCE; Number gxzminus = (gxpym(2) - gxmym(2)) / 2. / TOLERANCE; // xyz derivative Ue(current_dof) = (gxzplus - gxzminus) / 2. / TOLERANCE; dof_is_fixed[current_dof] = true; current_dof++; } } } // Assume that other C_ONE elements have a single nodal // value shape function and nodal gradient component // shape functions else if (cont == C_ONE) { libmesh_assert(nc == 1 + dim); _current_node = _current_elem->get_node(n); Ue(current_dof) = value(*_current_node); dof_is_fixed[current_dof] = true; current_dof++; Gradient grad = gradient(*_current_node); for (unsigned int i=0; i != dim; ++i) { Ue(current_dof) = grad(i); dof_is_fixed[current_dof] = true; current_dof++; } } else libmesh_error(); } // loop over nodes // From here on out we won't be sampling at nodes anymore _current_node = NULL; // In 3D, project any edge values next if (dim > 2 && cont != DISCONTINUOUS) for (unsigned int e=0; e != _current_elem->n_edges(); ++e) { FEInterface::dofs_on_edge(_current_elem, dim, fe_type, e, side_dofs); // Some edge dofs are on nodes and already // fixed, others are free to calculate unsigned int free_dofs = 0; for (unsigned int i=0; i != side_dofs.size(); ++i) if (!dof_is_fixed[side_dofs[i]]) free_dof[free_dofs++] = i; // There may be nothing to project if (!free_dofs) continue; Ke.resize (free_dofs, free_dofs); Ke.zero(); Fe.resize (free_dofs); Fe.zero(); // The new edge coefficients DenseVector<Number> Uedge(free_dofs); // Initialize FE data on the edge fe->attach_quadrature_rule (qedgerule.get()); fe->edge_reinit (_current_elem, e); const unsigned int n_qp = qedgerule->n_points(); _fe_problem.sizeZeroes(n_qp, _tid); // Loop over the quadrature points for (unsigned int qp = 0; qp < n_qp; qp++) { // solution at the quadrature point Number fineval = value(xyz_values[qp]); // solution grad at the quadrature point Gradient finegrad; if (cont == C_ONE) finegrad = gradient(xyz_values[qp]); // Form edge projection matrix for (unsigned int sidei = 0, freei = 0; sidei != side_dofs.size(); ++sidei) { unsigned int i = side_dofs[sidei]; // fixed DoFs aren't test functions if (dof_is_fixed[i]) continue; for (unsigned int sidej = 0, freej = 0; sidej != side_dofs.size(); ++sidej) { unsigned int j = side_dofs[sidej]; if (dof_is_fixed[j]) Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp] * Ue(j); else Ke(freei,freej) += phi[i][qp] * phi[j][qp] * JxW[qp]; if (cont == C_ONE) { if (dof_is_fixed[j]) Fe(freei) -= ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp] * Ue(j); else Ke(freei,freej) += ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp]; } if (!dof_is_fixed[j]) freej++; } Fe(freei) += phi[i][qp] * fineval * JxW[qp]; if (cont == C_ONE) Fe(freei) += (finegrad * (*dphi)[i][qp]) * JxW[qp]; freei++; } } Ke.cholesky_solve(Fe, Uedge); // Transfer new edge solutions to element for (unsigned int i=0; i != free_dofs; ++i) { Number &ui = Ue(side_dofs[free_dof[i]]); libmesh_assert(std::abs(ui) < TOLERANCE || std::abs(ui - Uedge(i)) < TOLERANCE); ui = Uedge(i); dof_is_fixed[side_dofs[free_dof[i]]] = true; } } // Project any side values (edges in 2D, faces in 3D) if (dim > 1 && cont != DISCONTINUOUS) for (unsigned int s=0; s != _current_elem->n_sides(); ++s) { FEInterface::dofs_on_side(_current_elem, dim, fe_type, s, side_dofs); // Some side dofs are on nodes/edges and already // fixed, others are free to calculate unsigned int free_dofs = 0; for (unsigned int i=0; i != side_dofs.size(); ++i) if (!dof_is_fixed[side_dofs[i]]) free_dof[free_dofs++] = i; // There may be nothing to project if (!free_dofs) continue; Ke.resize (free_dofs, free_dofs); Ke.zero(); Fe.resize (free_dofs); Fe.zero(); // The new side coefficients DenseVector<Number> Uside(free_dofs); // Initialize FE data on the side fe->attach_quadrature_rule (qsiderule.get()); fe->reinit (_current_elem, s); const unsigned int n_qp = qsiderule->n_points(); _fe_problem.sizeZeroes(n_qp, _tid); // Loop over the quadrature points for (unsigned int qp = 0; qp < n_qp; qp++) { // solution at the quadrature point Number fineval = value(xyz_values[qp]); // solution grad at the quadrature point Gradient finegrad; if (cont == C_ONE) finegrad = gradient(xyz_values[qp]); // Form side projection matrix for (unsigned int sidei = 0, freei = 0; sidei != side_dofs.size(); ++sidei) { unsigned int i = side_dofs[sidei]; // fixed DoFs aren't test functions if (dof_is_fixed[i]) continue; for (unsigned int sidej = 0, freej = 0; sidej != side_dofs.size(); ++sidej) { unsigned int j = side_dofs[sidej]; if (dof_is_fixed[j]) Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp] * Ue(j); else Ke(freei,freej) += phi[i][qp] * phi[j][qp] * JxW[qp]; if (cont == C_ONE) { if (dof_is_fixed[j]) Fe(freei) -= ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp] * Ue(j); else Ke(freei,freej) += ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp]; } if (!dof_is_fixed[j]) freej++; } Fe(freei) += (fineval * phi[i][qp]) * JxW[qp]; if (cont == C_ONE) Fe(freei) += (finegrad * (*dphi)[i][qp]) * JxW[qp]; freei++; } } Ke.cholesky_solve(Fe, Uside); // Transfer new side solutions to element for (unsigned int i=0; i != free_dofs; ++i) { Number &ui = Ue(side_dofs[free_dof[i]]); libmesh_assert(std::abs(ui) < TOLERANCE || std::abs(ui - Uside(i)) < TOLERANCE); ui = Uside(i); dof_is_fixed[side_dofs[free_dof[i]]] = true; } } // Project the interior values, finally // Some interior dofs are on nodes/edges/sides and // already fixed, others are free to calculate unsigned int free_dofs = 0; for (unsigned int i=0; i != n_dofs; ++i) if (!dof_is_fixed[i]) free_dof[free_dofs++] = i; // There may be nothing to project if (free_dofs) { Ke.resize (free_dofs, free_dofs); Ke.zero(); Fe.resize (free_dofs); Fe.zero(); // The new interior coefficients DenseVector<Number> Uint(free_dofs); // Initialize FE data fe->attach_quadrature_rule (qrule.get()); fe->reinit (_current_elem); const unsigned int n_qp = qrule->n_points(); _fe_problem.sizeZeroes(n_qp, _tid); // Loop over the quadrature points for (unsigned int qp=0; qp<n_qp; qp++) { // solution at the quadrature point Number fineval = value(xyz_values[qp]); // solution grad at the quadrature point Gradient finegrad; if (cont == C_ONE) finegrad = gradient(xyz_values[qp]); // Form interior projection matrix for (unsigned int i=0, freei=0; i != n_dofs; ++i) { // fixed DoFs aren't test functions if (dof_is_fixed[i]) continue; for (unsigned int j=0, freej=0; j != n_dofs; ++j) { if (dof_is_fixed[j]) Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp] * Ue(j); else Ke(freei,freej) += phi[i][qp] * phi[j][qp] * JxW[qp]; if (cont == C_ONE) { if (dof_is_fixed[j]) Fe(freei) -= ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp] * Ue(j); else Ke(freei,freej) += ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp]; } if (!dof_is_fixed[j]) freej++; } Fe(freei) += phi[i][qp] * fineval * JxW[qp]; if (cont == C_ONE) Fe(freei) += (finegrad * (*dphi)[i][qp]) * JxW[qp]; freei++; } } Ke.cholesky_solve(Fe, Uint); // Transfer new interior solutions to element for (unsigned int i=0; i != free_dofs; ++i) { Number &ui = Ue(free_dof[i]); libmesh_assert(std::abs(ui) < TOLERANCE || std::abs(ui - Uint(i)) < TOLERANCE); ui = Uint(i); dof_is_fixed[free_dof[i]] = true; } } // if there are free interior dofs // Make sure every DoF got reached! for (unsigned int i=0; i != n_dofs; ++i) libmesh_assert(dof_is_fixed[i]); NumericVector<Number> & solution = _var.sys().solution(); // 'first' and 'last' are no longer used, see note about subdomain-restricted variables below // const dof_id_type // first = solution.first_local_index(), // last = solution.last_local_index(); // Lock the new_vector since it is shared among threads. { Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); for (unsigned int i = 0; i < n_dofs; i++) // We may be projecting a new zero value onto // an old nonzero approximation - RHS // if (Ue(i) != 0.) // This is commented out because of subdomain restricted variables. // It can be the case that if a subdomain restricted variable's boundary // aligns perfectly with a processor boundary that the variable will get // no value. To counteract this we're going to let every processor set a // value at every node and then let PETSc figure it out. // Later we can choose to do something different / better. // if ((dof_indices[i] >= first) && (dof_indices[i] < last)) { solution.set(dof_indices[i], Ue(i)); if (cont == C_ZERO) _var.setNodalValue(Ue(i), i); } } }
// // // // We now define the matrix assembly function for the // Poisson system. We need to first compute element // matrices and right-hand sides, and then take into // account the boundary conditions, which will be handled // via a penalty method. void assemble_poisson(EquationSystems& es, const std::string& system_name) { // It is a good idea to make sure we are assembling // the proper system. libmesh_assert_equal_to (system_name, "Poisson"); // Declare a performance log. Give it a descriptive // string to identify what part of the code we are // logging, since there may be many PerfLogs in an // application. PerfLog perf_log ("Matrix Assembly"); // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); // Get a reference to the LinearImplicitSystem we are solving LinearImplicitSystem& system = es.get_system<LinearImplicitSystem>("Poisson"); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = system.get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p UniquePtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); // A 5th order Gauss quadrature rule for numerical integration. QGauss qrule (dim, FIFTH); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (&qrule); // Declare a special finite element object for // boundary integration. UniquePtr<FEBase> fe_face (FEBase::build(dim, fe_type)); // Boundary integration requires one quadraure rule, // with dimensionality one less than the dimensionality // of the element. QGauss qface(dim-1, FIFTH); // Tell the finte element object to use our // quadrature rule. fe_face->attach_quadrature_rule (&qface); // Here we define some references to cell-specific data that // will be used to assemble the linear system. // We begin with the element Jacobian * quadrature weight at each // integration point. const std::vector<Real>& JxW = fe->get_JxW(); // The physical XY locations of the quadrature points on the element. // These might be useful for evaluating spatially varying material // properties at the quadrature points. const std::vector<Point>& q_point = fe->get_xyz(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> >& phi = fe->get_phi(); // The element shape function gradients evaluated at the quadrature // points. const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // Define data structures to contain the element matrix // and right-hand-side vector contribution. Following // basic finite element terminology we will denote these // "Ke" and "Fe". More detail is in example 3. DenseMatrix<Number> Ke; DenseVector<Number> Fe; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices, dof_indices2; // Now we will loop over all the elements in the mesh. // We will compute the element matrix and right-hand-side // contribution. See example 3 for a discussion of the // element iterators. Here we use the \p const_local_elem_iterator // to indicate we only want to loop over elements that are assigned // to the local processor. This allows each processor to compute // its components of the global matrix. // // "PARALLEL CHANGE" MeshBase::const_element_iterator el = mesh.local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.local_elements_end(); for ( ; el != end_el; ++el) { // Start logging the shape function initialization. // This is done through a simple function call with // the name of the event to log. perf_log.push("elem init"); // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices,0); dof_map.dof_indices (elem, dof_indices2,1); // std::cout << "dof_indices.size()=" // << dof_indices.size() // << ", dof_indices2.size()=" // << dof_indices2.size() // << std::endl; // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe->reinit (elem); // Zero the element matrix and right-hand side before // summing them. We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Ke.resize (std::max(dof_indices.size(), dof_indices2.size()), std::max(dof_indices.size(), dof_indices2.size())); Fe.resize (std::max(dof_indices.size(), dof_indices2.size())); // Stop logging the shape function initialization. // If you forget to stop logging an event the PerfLog // object will probably catch the error and abort. perf_log.pop("elem init"); // Now we will build the element matrix. This involves // a double loop to integrate the test funcions (i) against // the trial functions (j). // // We have split the numeric integration into two loops // so that we can log the matrix and right-hand-side // computation seperately. // // Now start logging the element matrix computation perf_log.push ("Ke"); for (unsigned int qp=0; qp<qrule.n_points(); qp++) for (unsigned int i=0; i<phi.size(); i++) for (unsigned int j=0; j<phi.size(); j++) Ke(i,j) += JxW[qp]*(dphi[i][qp]*dphi[j][qp]); // Stop logging the matrix computation perf_log.pop ("Ke"); // Now we build the element right-hand-side contribution. // This involves a single loop in which we integrate the // "forcing function" in the PDE against the test functions. // // Start logging the right-hand-side computation perf_log.push ("Fe"); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { // fxy is the forcing function for the Poisson equation. // In this case we set fxy to be a finite difference // Laplacian approximation to the (known) exact solution. // // We will use the second-order accurate FD Laplacian // approximation, which in 2D on a structured grid is // // u_xx + u_yy = (u(i-1,j) + u(i+1,j) + // u(i,j-1) + u(i,j+1) + // -4*u(i,j))/h^2 // // Since the value of the forcing function depends only // on the location of the quadrature point (q_point[qp]) // we will compute it here, outside of the i-loop const Real x = q_point[qp](0); #if LIBMESH_DIM > 1 const Real y = q_point[qp](1); #else const Real y = 0; #endif #if LIBMESH_DIM > 2 const Real z = q_point[qp](2); #else const Real z = 0; #endif const Real eps = 1.e-3; const Real uxx = (exact_solution(x-eps,y,z) + exact_solution(x+eps,y,z) + -2.*exact_solution(x,y,z))/eps/eps; const Real uyy = (exact_solution(x,y-eps,z) + exact_solution(x,y+eps,z) + -2.*exact_solution(x,y,z))/eps/eps; const Real uzz = (exact_solution(x,y,z-eps) + exact_solution(x,y,z+eps) + -2.*exact_solution(x,y,z))/eps/eps; Real fxy; if(dim==1) { // In 1D, compute the rhs by differentiating the // exact solution twice. const Real pi = libMesh::pi; fxy = (0.25*pi*pi)*sin(.5*pi*x); } else { fxy = - (uxx + uyy + ((dim==2) ? 0. : uzz)); } // Add the RHS contribution for (unsigned int i=0; i<phi.size(); i++) Fe(i) += JxW[qp]*fxy*phi[i][qp]; } // Stop logging the right-hand-side computation perf_log.pop ("Fe"); // At this point the interior element integration has // been completed. However, we have not yet addressed // boundary conditions. For this example we will only // consider simple Dirichlet boundary conditions imposed // via the penalty method. This is discussed at length in // example 3. { // Start logging the boundary condition computation perf_log.push ("BCs"); // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. for (unsigned int side=0; side<elem->n_sides(); side++) if ((elem->neighbor(side) == NULL) || (elem->neighbor(side)->subdomain_id() != elem->subdomain_id())) { // The penalty value. \frac{1}{\epsilon} // in the discussion above. const Real penalty = 1.e10; // The value of the shape functions at the quadrature // points. const std::vector<std::vector<Real> >& phi_face = fe_face->get_phi(); // The Jacobian * Quadrature Weight at the quadrature // points on the face. const std::vector<Real>& JxW_face = fe_face->get_JxW(); // The XYZ locations (in physical space) of the // quadrature points on the face. This is where // we will interpolate the boundary value function. const std::vector<Point >& qface_point = fe_face->get_xyz(); // Compute the shape function values on the element // face. fe_face->reinit(elem, side); // Loop over the face quadrature points for integration. for (unsigned int qp=0; qp<qface.n_points(); qp++) { // The location on the boundary of the current // face quadrature point. const Real xf = qface_point[qp](0); #if LIBMESH_DIM > 1 const Real yf = qface_point[qp](1); #else const Real yf = 0.; #endif #if LIBMESH_DIM > 2 const Real zf = qface_point[qp](2); #else const Real zf = 0.; #endif // The boundary value. const Real value = exact_solution(xf, yf, zf); // Matrix contribution of the L2 projection. for (unsigned int i=0; i<phi_face.size(); i++) for (unsigned int j=0; j<phi_face.size(); j++) Ke(i,j) += JxW_face[qp]*penalty*phi_face[i][qp]*phi_face[j][qp]; // Right-hand-side contribution of the L2 // projection. for (unsigned int i=0; i<phi_face.size(); i++) Fe(i) += JxW_face[qp]*penalty*value*phi_face[i][qp]; } } // Stop logging the boundary condition computation perf_log.pop ("BCs"); } // The element matrix and right-hand-side are now built // for this element. Add them to the global matrix and // right-hand-side vector. The \p PetscMatrix::add_matrix() // and \p PetscVector::add_vector() members do this for us. // Start logging the insertion of the local (element) // matrix and vector into the global matrix and vector perf_log.push ("matrix insertion"); if (dof_indices.size()) { system.matrix->add_matrix (Ke, dof_indices); system.rhs->add_vector (Fe, dof_indices); } if (dof_indices2.size()) { system.matrix->add_matrix (Ke, dof_indices2); system.rhs->add_vector (Fe, dof_indices2); } // Start logging the insertion of the local (element) // matrix and vector into the global matrix and vector perf_log.pop ("matrix insertion"); } // That's it. We don't need to do anything else to the // PerfLog. When it goes out of scope (at this function return) // it will print its log to the screen. Pretty easy, huh? }
void assemble_elasticity(EquationSystems& es, const std::string& system_name) { libmesh_assert_equal_to (system_name, "Elasticity"); const MeshBase& mesh = es.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); LinearImplicitSystem& system = es.get_system<LinearImplicitSystem>("Elasticity"); const unsigned int u_var = system.variable_number ("u"); const unsigned int v_var = system.variable_number ("v"); const unsigned int lambda_var = system.variable_number ("lambda"); const DofMap& dof_map = system.get_dof_map(); FEType fe_type = dof_map.variable_type(0); UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); QGauss qrule (dim, fe_type.default_quadrature_order()); fe->attach_quadrature_rule (&qrule); UniquePtr<FEBase> fe_face (FEBase::build(dim, fe_type)); QGauss qface(dim-1, fe_type.default_quadrature_order()); fe_face->attach_quadrature_rule (&qface); const std::vector<Real>& JxW = fe->get_JxW(); const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); DenseMatrix<Number> Ke; DenseVector<Number> Fe; DenseSubMatrix<Number> Kuu(Ke), Kuv(Ke), Kvu(Ke), Kvv(Ke); DenseSubMatrix<Number> Klambda_v(Ke), Kv_lambda(Ke); DenseSubVector<Number> Fu(Fe), Fv(Fe); std::vector<dof_id_type> dof_indices; std::vector<dof_id_type> dof_indices_u; std::vector<dof_id_type> dof_indices_v; std::vector<dof_id_type> dof_indices_lambda; MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { const Elem* elem = *el; dof_map.dof_indices (elem, dof_indices); dof_map.dof_indices (elem, dof_indices_u, u_var); dof_map.dof_indices (elem, dof_indices_v, v_var); dof_map.dof_indices (elem, dof_indices_lambda, lambda_var); const unsigned int n_dofs = dof_indices.size(); const unsigned int n_u_dofs = dof_indices_u.size(); const unsigned int n_v_dofs = dof_indices_v.size(); const unsigned int n_lambda_dofs = dof_indices_lambda.size(); fe->reinit (elem); Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs); Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs); Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs); Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs); // Also, add a row and a column to enforce the constraint Kv_lambda.reposition (v_var*n_u_dofs, v_var*n_u_dofs+n_v_dofs, n_v_dofs, 1); Klambda_v.reposition (v_var*n_v_dofs+n_v_dofs, v_var*n_v_dofs, 1, n_v_dofs); Fu.reposition (u_var*n_u_dofs, n_u_dofs); Fv.reposition (v_var*n_u_dofs, n_v_dofs); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { for (unsigned int i=0; i<n_u_dofs; i++) for (unsigned int j=0; j<n_u_dofs; j++) { // Tensor indices unsigned int C_i, C_j, C_k, C_l; C_i=0, C_k=0; C_j=0, C_l=0; Kuu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=0; Kuu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=0, C_l=1; Kuu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=1; Kuu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); } for (unsigned int i=0; i<n_u_dofs; i++) for (unsigned int j=0; j<n_v_dofs; j++) { // Tensor indices unsigned int C_i, C_j, C_k, C_l; C_i=0, C_k=1; C_j=0, C_l=0; Kuv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=0; Kuv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=0, C_l=1; Kuv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=1; Kuv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); } for (unsigned int i=0; i<n_v_dofs; i++) for (unsigned int j=0; j<n_u_dofs; j++) { // Tensor indices unsigned int C_i, C_j, C_k, C_l; C_i=1, C_k=0; C_j=0, C_l=0; Kvu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=0; Kvu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=0, C_l=1; Kvu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=1; Kvu(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); } for (unsigned int i=0; i<n_v_dofs; i++) for (unsigned int j=0; j<n_v_dofs; j++) { // Tensor indices unsigned int C_i, C_j, C_k, C_l; C_i=1, C_k=1; C_j=0, C_l=0; Kvv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=0; Kvv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=0, C_l=1; Kvv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); C_j=1, C_l=1; Kvv(i,j) += JxW[qp]*(eval_elasticity_tensor(C_i,C_j,C_k,C_l) * dphi[i][qp](C_j)*dphi[j][qp](C_l)); } } { for (unsigned int side=0; side<elem->n_sides(); side++) if (elem->neighbor(side) == NULL) { const std::vector<boundary_id_type> bc_ids = mesh.get_boundary_info().boundary_ids (elem,side); const std::vector<std::vector<Real> >& phi_face = fe_face->get_phi(); const std::vector<Real>& JxW_face = fe_face->get_JxW(); fe_face->reinit(elem, side); for (std::vector<boundary_id_type>::const_iterator b = bc_ids.begin(); b != bc_ids.end(); ++b) { const boundary_id_type bc_id = *b; for (unsigned int qp=0; qp<qface.n_points(); qp++) { // Add the loading if( bc_id == 2 ) { for (unsigned int i=0; i<n_v_dofs; i++) { Fv(i) += JxW_face[qp]* (-1.) * phi_face[i][qp]; } } // Add the constraint contributions if( bc_id == 1 ) { for (unsigned int i=0; i<n_v_dofs; i++) for (unsigned int j=0; j<n_lambda_dofs; j++) { Kv_lambda(i,j) += JxW_face[qp]* (-1.) * phi_face[i][qp]; } for (unsigned int i=0; i<n_lambda_dofs; i++) for (unsigned int j=0; j<n_v_dofs; j++) { Klambda_v(i,j) += JxW_face[qp]* (-1.) * phi_face[j][qp]; } } } } } } dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); system.matrix->add_matrix (Ke, dof_indices); system.rhs->add_vector (Fe, dof_indices); } }
int main(int argc, char ** argv) { LibMeshInit init(argc, argv); GetPot cl(argc, argv); unsigned char dim = -1; if (!cl.search("--dim")) { libMesh::err << "No --dim argument found!" << std::endl; usage_error(argv[0]); } dim = cl.next(dim); Mesh mesh(init.comm(), dim); if(!cl.search("--input")) { libMesh::err << "No --input argument found!" << std::endl; usage_error(argv[0]); } const char * meshname = cl.next("mesh.xda"); mesh.read(meshname); libMesh::out << "Loaded mesh " << meshname << std::endl; if(!cl.search("--newbcid")) { libMesh::err << "No --bcid argument found!" << std::endl; usage_error(argv[0]); } boundary_id_type bcid = 0; bcid = cl.next(bcid); Point minnormal(-std::numeric_limits<Real>::max(), -std::numeric_limits<Real>::max(), -std::numeric_limits<Real>::max()); Point maxnormal(std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max()); Point minpoint(-std::numeric_limits<Real>::max(), -std::numeric_limits<Real>::max(), -std::numeric_limits<Real>::max()); Point maxpoint(std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max()); if (cl.search("--minnormalx")) minnormal(0) = cl.next(minnormal(0)); if (cl.search("--minnormalx")) minnormal(0) = cl.next(minnormal(0)); if (cl.search("--maxnormalx")) maxnormal(0) = cl.next(maxnormal(0)); if (cl.search("--minnormaly")) minnormal(1) = cl.next(minnormal(1)); if (cl.search("--maxnormaly")) maxnormal(1) = cl.next(maxnormal(1)); if (cl.search("--minnormalz")) minnormal(2) = cl.next(minnormal(2)); if (cl.search("--maxnormalz")) maxnormal(2) = cl.next(maxnormal(2)); if (cl.search("--minpointx")) minpoint(0) = cl.next(minpoint(0)); if (cl.search("--maxpointx")) maxpoint(0) = cl.next(maxpoint(0)); if (cl.search("--minpointy")) minpoint(1) = cl.next(minpoint(1)); if (cl.search("--maxpointy")) maxpoint(1) = cl.next(maxpoint(1)); if (cl.search("--minpointz")) minpoint(2) = cl.next(minpoint(2)); if (cl.search("--maxpointz")) maxpoint(2) = cl.next(maxpoint(2)); libMesh::out << "min point = " << minpoint << std::endl; libMesh::out << "max point = " << maxpoint << std::endl; libMesh::out << "min normal = " << minnormal << std::endl; libMesh::out << "max normal = " << maxnormal << std::endl; bool matcholdbcid = false; boundary_id_type oldbcid = 0; if (cl.search("--oldbcid")) { matcholdbcid = true; oldbcid = cl.next(oldbcid); if (oldbcid < 0) oldbcid = BoundaryInfo::invalid_id; } UniquePtr<FEBase> fe = FEBase::build(dim, FEType(FIRST,LAGRANGE)); QGauss qface(dim-1, CONSTANT); fe->attach_quadrature_rule(&qface); const std::vector<Point> & face_points = fe->get_xyz(); const std::vector<Point> & face_normals = fe->get_normals(); MeshBase::element_iterator el = mesh.elements_begin(); const MeshBase::element_iterator end_el = mesh.elements_end(); for (; el != end_el; ++el) { Elem * elem = *el; unsigned int n_sides = elem->n_sides(); // Container to catch ids handed back from BoundaryInfo std::vector<boundary_id_type> ids; for (unsigned short s=0; s != n_sides; ++s) { if (elem->neighbor_ptr(s)) continue; fe->reinit(elem,s); const Point & p = face_points[0]; const Point & n = face_normals[0]; //libMesh::out << "elem = " << elem->id() << std::endl; //libMesh::out << "centroid = " << elem->centroid() << std::endl; //libMesh::out << "p = " << p << std::endl; //libMesh::out << "n = " << n << std::endl; if (p(0) > minpoint(0) && p(0) < maxpoint(0) && p(1) > minpoint(1) && p(1) < maxpoint(1) && p(2) > minpoint(2) && p(2) < maxpoint(2) && n(0) > minnormal(0) && n(0) < maxnormal(0) && n(1) > minnormal(1) && n(1) < maxnormal(1) && n(2) > minnormal(2) && n(2) < maxnormal(2)) { // Get the list of boundary ids for this side mesh.get_boundary_info().boundary_ids(elem, s, ids); // There should be at most one value present, otherwise the // logic here won't work. libmesh_assert(ids.size() <= 1); // A convenient name for the side's ID. boundary_id_type b_id = ids.empty() ? BoundaryInfo::invalid_id : ids[0]; if (matcholdbcid && b_id != oldbcid) continue; mesh.get_boundary_info().remove_side(elem, s); mesh.get_boundary_info().add_side(elem, s, bcid); //libMesh::out << "Set element " << elem->id() << " side " << s << // " to boundary " << bcid << std::endl; } } } std::string outputname; if(cl.search("--output")) { outputname = cl.next("mesh.xda"); } else { outputname = "new."; outputname += meshname; } mesh.write(outputname.c_str()); libMesh::out << "Wrote mesh " << outputname << std::endl; return 0; }
void assemble_stokes (EquationSystems & es, const std::string & system_name) { // It is a good idea to make sure we are assembling // the proper system. libmesh_assert_equal_to (system_name, "Stokes"); // Get a constant reference to the mesh object. const MeshBase & mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); // Get a reference to the Convection-Diffusion system object. LinearImplicitSystem & system = es.get_system<LinearImplicitSystem> ("Stokes"); // Numeric ids corresponding to each variable in the system const unsigned int u_var = system.variable_number ("u"); const unsigned int v_var = system.variable_number ("v"); const unsigned int p_var = system.variable_number ("p"); // Get the Finite Element type for "u". Note this will be // the same as the type for "v". FEType fe_vel_type = system.variable_type(u_var); // Get the Finite Element type for "p". FEType fe_pres_type = system.variable_type(p_var); // Build a Finite Element object of the specified type for // the velocity variables. UniquePtr<FEBase> fe_vel (FEBase::build(dim, fe_vel_type)); // Build a Finite Element object of the specified type for // the pressure variables. UniquePtr<FEBase> fe_pres (FEBase::build(dim, fe_pres_type)); // A Gauss quadrature rule for numerical integration. // Let the \p FEType object decide what order rule is appropriate. QGauss qrule (dim, fe_vel_type.default_quadrature_order()); // Tell the finite element objects to use our quadrature rule. fe_vel->attach_quadrature_rule (&qrule); fe_pres->attach_quadrature_rule (&qrule); // Here we define some references to cell-specific data that // will be used to assemble the linear system. // // The element Jacobian * quadrature weight at each integration point. const std::vector<Real> & JxW = fe_vel->get_JxW(); // The element shape function gradients for the velocity // variables evaluated at the quadrature points. const std::vector<std::vector<RealGradient> > & dphi = fe_vel->get_dphi(); // The element shape functions for the pressure variable // evaluated at the quadrature points. const std::vector<std::vector<Real> > & psi = fe_pres->get_phi(); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap & dof_map = system.get_dof_map(); // Define data structures to contain the element matrix // and right-hand-side vector contribution. Following // basic finite element terminology we will denote these // "Ke" and "Fe". DenseMatrix<Number> Ke; DenseVector<Number> Fe; DenseSubMatrix<Number> Kuu(Ke), Kuv(Ke), Kup(Ke), Kvu(Ke), Kvv(Ke), Kvp(Ke), Kpu(Ke), Kpv(Ke), Kpp(Ke); DenseSubVector<Number> Fu(Fe), Fv(Fe), Fp(Fe); // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices; std::vector<dof_id_type> dof_indices_u; std::vector<dof_id_type> dof_indices_v; std::vector<dof_id_type> dof_indices_p; // Now we will loop over all the elements in the mesh that // live on the local processor. We will compute the element // matrix and right-hand-side contribution. In case users later // modify this program to include refinement, we will be safe and // will only consider the active elements; hence we use a variant of // the \p active_elem_iterator. MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem * elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); dof_map.dof_indices (elem, dof_indices_u, u_var); dof_map.dof_indices (elem, dof_indices_v, v_var); dof_map.dof_indices (elem, dof_indices_p, p_var); const unsigned int n_dofs = dof_indices.size(); const unsigned int n_u_dofs = dof_indices_u.size(); const unsigned int n_v_dofs = dof_indices_v.size(); const unsigned int n_p_dofs = dof_indices_p.size(); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe_vel->reinit (elem); fe_pres->reinit (elem); // Zero the element matrix and right-hand side before // summing them. We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); // Reposition the submatrices... The idea is this: // // - - - - // | Kuu Kuv Kup | | Fu | // Ke = | Kvu Kvv Kvp |; Fe = | Fv | // | Kpu Kpv Kpp | | Fp | // - - - - // // The \p DenseSubMatrix.repostition () member takes the // (row_offset, column_offset, row_size, column_size). // // Similarly, the \p DenseSubVector.reposition () member // takes the (row_offset, row_size) Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs); Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs); Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs); Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs); Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs); Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs); Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs); Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs); Kpp.reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs); Fu.reposition (u_var*n_u_dofs, n_u_dofs); Fv.reposition (v_var*n_u_dofs, n_v_dofs); Fp.reposition (p_var*n_u_dofs, n_p_dofs); // Now we will build the element matrix. for (unsigned int qp=0; qp<qrule.n_points(); qp++) { // Assemble the u-velocity row // uu coupling for (unsigned int i=0; i<n_u_dofs; i++) for (unsigned int j=0; j<n_u_dofs; j++) Kuu(i,j) += JxW[qp]*(dphi[i][qp]*dphi[j][qp]); // up coupling for (unsigned int i=0; i<n_u_dofs; i++) for (unsigned int j=0; j<n_p_dofs; j++) Kup(i,j) += -JxW[qp]*psi[j][qp]*dphi[i][qp](0); // Assemble the v-velocity row // vv coupling for (unsigned int i=0; i<n_v_dofs; i++) for (unsigned int j=0; j<n_v_dofs; j++) Kvv(i,j) += JxW[qp]*(dphi[i][qp]*dphi[j][qp]); // vp coupling for (unsigned int i=0; i<n_v_dofs; i++) for (unsigned int j=0; j<n_p_dofs; j++) Kvp(i,j) += -JxW[qp]*psi[j][qp]*dphi[i][qp](1); // Assemble the pressure row // pu coupling for (unsigned int i=0; i<n_p_dofs; i++) for (unsigned int j=0; j<n_u_dofs; j++) Kpu(i,j) += -JxW[qp]*psi[i][qp]*dphi[j][qp](0); // pv coupling for (unsigned int i=0; i<n_p_dofs; i++) for (unsigned int j=0; j<n_v_dofs; j++) Kpv(i,j) += -JxW[qp]*psi[i][qp]*dphi[j][qp](1); } // end of the quadrature point qp-loop // At this point the interior element integration has // been completed. However, we have not yet addressed // boundary conditions. For this example we will only // consider simple Dirichlet boundary conditions imposed // via the penalty method. The penalty method used here // is equivalent (for Lagrange basis functions) to lumping // the matrix resulting from the L2 projection penalty // approach introduced in example 3. { // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. for (unsigned int s=0; s<elem->n_sides(); s++) if (elem->neighbor(s) == NULL) { UniquePtr<Elem> side (elem->build_side(s)); // Loop over the nodes on the side. for (unsigned int ns=0; ns<side->n_nodes(); ns++) { // The location on the boundary of the current // node. // const Real xf = side->point(ns)(0); const Real yf = side->point(ns)(1); // The penalty value. \f$ \frac{1}{\epsilon \f$ const Real penalty = 1.e10; // The boundary values. // Set u = 1 on the top boundary, 0 everywhere else const Real u_value = (yf > .99) ? 1. : 0.; // Set v = 0 everywhere const Real v_value = 0.; // Find the node on the element matching this node on // the side. That defined where in the element matrix // the boundary condition will be applied. for (unsigned int n=0; n<elem->n_nodes(); n++) if (elem->node(n) == side->node(ns)) { // Matrix contribution. Kuu(n,n) += penalty; Kvv(n,n) += penalty; // Right-hand-side contribution. Fu(n) += penalty*u_value; Fv(n) += penalty*v_value; } } // end face node loop } // end if (elem->neighbor(side) == NULL) } // end boundary condition section // If this assembly program were to be used on an adaptive mesh, // we would have to apply any hanging node constraint equations. dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); // The element matrix and right-hand-side are now built // for this element. Add them to the global matrix and // right-hand-side vector. The \p NumericMatrix::add_matrix() // and \p NumericVector::add_vector() members do this for us. system.matrix->add_matrix (Ke, dof_indices); system.rhs->add_vector (Fe, dof_indices); } // end of element loop }
NS_InitXPCOM2(nsIServiceManager** aResult, nsIFile* aBinDirectory, nsIDirectoryServiceProvider* aAppFileLocationProvider) { static bool sInitialized = false; if (sInitialized) { return NS_ERROR_FAILURE; } sInitialized = true; mozPoisonValueInit(); NS_LogInit(); NS_InitAtomTable(); mozilla::LogModule::Init(); JS_SetCurrentEmbedderTimeFunction(TimeSinceProcessCreation); char aLocal; profiler_init(&aLocal); nsresult rv = NS_OK; // We are not shutting down gXPCOMShuttingDown = false; // Initialize the available memory tracker before other threads have had a // chance to start up, because the initialization is not thread-safe. mozilla::AvailableMemoryTracker::Init(); #ifdef XP_UNIX // Discover the current value of the umask, and save it where // nsSystemInfo::Init can retrieve it when necessary. There is no way // to read the umask without changing it, and the setting is process- // global, so this must be done while we are still single-threaded; the // nsSystemInfo object is typically created much later, when some piece // of chrome JS wants it. The system call is specified as unable to fail. nsSystemInfo::gUserUmask = ::umask(0777); ::umask(nsSystemInfo::gUserUmask); #endif // Set up chromium libs NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!"); if (!AtExitManager::AlreadyRegistered()) { sExitManager = new AtExitManager(); } MessageLoop* messageLoop = MessageLoop::current(); if (!messageLoop) { sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT); sMessageLoop->set_thread_name("Gecko"); // Set experimental values for main thread hangs: // 128ms for transient hangs and 8192ms for permanent hangs sMessageLoop->set_hang_timeouts(128, 8192); } else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) { messageLoop->set_thread_name("Gecko_Child"); messageLoop->set_hang_timeouts(128, 8192); } if (XRE_IsParentProcess() && !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) { UniquePtr<BrowserProcessSubThread> ioThread = MakeUnique<BrowserProcessSubThread>(BrowserProcessSubThread::IO); base::Thread::Options options; options.message_loop_type = MessageLoop::TYPE_IO; if (NS_WARN_IF(!ioThread->StartWithOptions(options))) { return NS_ERROR_FAILURE; } sIOThread = ioThread.release(); } // Establish the main thread here. rv = nsThreadManager::get()->Init(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // Set up the timer globals/timer thread rv = nsTimerImpl::Startup(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } #ifndef ANDROID // If the locale hasn't already been setup by our embedder, // get us out of the "C" locale and into the system if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) { setlocale(LC_ALL, ""); } #endif #if defined(XP_UNIX) NS_StartupNativeCharsetUtils(); #endif NS_StartupLocalFile(); StartupSpecialSystemDirectory(); nsDirectoryService::RealInit(); bool value; if (aBinDirectory) { rv = aBinDirectory->IsDirectory(&value); if (NS_SUCCEEDED(rv) && value) { nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, aBinDirectory); } } if (aAppFileLocationProvider) { rv = nsDirectoryService::gService->RegisterProvider(aAppFileLocationProvider); if (NS_FAILED(rv)) { return rv; } } nsCOMPtr<nsIFile> xpcomLib; nsDirectoryService::gService->Get(NS_GRE_BIN_DIR, NS_GET_IID(nsIFile), getter_AddRefs(xpcomLib)); MOZ_ASSERT(xpcomLib); // set gGREBinPath nsAutoString path; xpcomLib->GetPath(path); gGREBinPath = ToNewUnicode(path); xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL)); nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib); if (!mozilla::Omnijar::IsInitialized()) { mozilla::Omnijar::Init(); } if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) { #ifdef OS_WIN CommandLine::Init(0, nullptr); #else nsCOMPtr<nsIFile> binaryFile; nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(binaryFile)); if (NS_WARN_IF(!binaryFile)) { return NS_ERROR_FAILURE; } rv = binaryFile->AppendNative(NS_LITERAL_CSTRING("nonexistent-executable")); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCString binaryPath; rv = binaryFile->GetNativePath(binaryPath); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } static char const* const argv = { strdup(binaryPath.get()) }; CommandLine::Init(1, &argv); #endif } NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr, "CompMgr not null at init"); // Create the Component/Service Manager nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl(); NS_ADDREF(nsComponentManagerImpl::gComponentManager); // Global cycle collector initialization. if (!nsCycleCollector_init()) { return NS_ERROR_UNEXPECTED; } // And start it up for this thread too. nsCycleCollector_startup(); // Register ICU memory functions. This really shouldn't be necessary: the // JS engine should do this on its own inside JS_Init, and memory-reporting // code should call a JSAPI function to observe ICU memory usage. But we // can't define the alloc/free functions in the JS engine, because it can't // depend on the XPCOM-based memory reporting goop. So for now, we have // this oddness. mozilla::SetICUMemoryFunctions(); // Do the same for libogg. ogg_set_mem_functions(OggReporter::CountingMalloc, OggReporter::CountingCalloc, OggReporter::CountingRealloc, OggReporter::CountingFree); #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING) // And for VPX. vpx_mem_set_functions(VPXReporter::CountingMalloc, VPXReporter::CountingCalloc, VPXReporter::CountingRealloc, VPXReporter::CountingFree, memcpy, memset, memmove); #endif #if EXPOSE_INTL_API && defined(MOZ_ICU_DATA_ARCHIVE) nsCOMPtr<nsIFile> greDir; nsDirectoryService::gService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir)); MOZ_ASSERT(greDir); nsAutoCString nativeGREPath; greDir->GetNativePath(nativeGREPath); u_setDataDirectory(nativeGREPath.get()); #endif // Initialize the JS engine. const char* jsInitFailureReason = JS_InitWithFailureDiagnostic(); if (jsInitFailureReason) { NS_RUNTIMEABORT(jsInitFailureReason); } rv = nsComponentManagerImpl::gComponentManager->Init(); if (NS_FAILED(rv)) { NS_RELEASE(nsComponentManagerImpl::gComponentManager); return rv; } if (aResult) { NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager); } // The iimanager constructor searches and registers XPT files. // (We trigger the singleton's lazy construction here to make that happen.) (void)XPTInterfaceInfoManager::GetSingleton(); // After autoreg, but before we actually instantiate any components, // add any services listed in the "xpcom-directory-providers" category // to the directory service. nsDirectoryService::gService->RegisterCategoryProviders(); // Init SharedThreadPool (which needs the service manager). SharedThreadPool::InitStatics(); // Init AbstractThread. AbstractThread::InitStatics(); // Force layout to spin up so that nsContentUtils is available for cx stack // munging. nsCOMPtr<nsISupports> componentLoader = do_GetService("@mozilla.org/moz/jsloader;1"); mozilla::scache::StartupCache::GetSingleton(); mozilla::AvailableMemoryTracker::Activate(); // Notify observers of xpcom autoregistration start NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr, NS_XPCOM_STARTUP_OBSERVER_ID); #ifdef XP_WIN CreateAnonTempFileRemover(); #endif // We only want the SystemMemoryReporter running in one process, because it // profiles the entire system. The main process is the obvious place for // it. if (XRE_IsParentProcess()) { mozilla::SystemMemoryReporter::Init(); } // The memory reporter manager is up and running -- register our reporters. RegisterStrongMemoryReporter(new ICUReporter()); RegisterStrongMemoryReporter(new OggReporter()); #ifdef MOZ_VPX RegisterStrongMemoryReporter(new VPXReporter()); #endif mozilla::Telemetry::Init(); mozilla::HangMonitor::Startup(); mozilla::BackgroundHangMonitor::Startup(); const MessageLoop* const loop = MessageLoop::current(); sMainHangMonitor = new mozilla::BackgroundHangMonitor( loop->thread_name().c_str(), loop->transient_hang_timeout(), loop->permanent_hang_timeout()); return NS_OK; }
TEST(stagefright_MPEG4Metadata, test_case_mp4) { for (size_t test = 0; test < ArrayLength(testFiles); ++test) { nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename); ASSERT_FALSE(buffer.IsEmpty()); RefPtr<Stream> stream = new TestStream(buffer.Elements(), buffer.Length()); EXPECT_TRUE(MP4Metadata::HasCompleteMetadata(stream)); RefPtr<MediaByteBuffer> metadataBuffer = MP4Metadata::Metadata(stream); EXPECT_TRUE(metadataBuffer); MP4Metadata metadata(stream); EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kUndefinedTrack)); EXPECT_EQ(testFiles[test].mNumberAudioTracks, metadata.GetNumberTracks(TrackInfo::kAudioTrack)); EXPECT_EQ(testFiles[test].mNumberVideoTracks, metadata.GetNumberTracks(TrackInfo::kVideoTrack)); EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kTextTrack)); EXPECT_EQ(0u, metadata.GetNumberTracks(static_cast<TrackInfo::TrackType>(-1))); EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0)); UniquePtr<TrackInfo> trackInfo = metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0); if (testFiles[test].mNumberVideoTracks == 0) { EXPECT_TRUE(!trackInfo); } else { ASSERT_TRUE(!!trackInfo); const VideoInfo* videoInfo = trackInfo->GetAsVideoInfo(); ASSERT_TRUE(!!videoInfo); EXPECT_TRUE(videoInfo->IsValid()); EXPECT_TRUE(videoInfo->IsVideo()); EXPECT_EQ(testFiles[test].mWidth, videoInfo->mDisplay.width); EXPECT_EQ(testFiles[test].mHeight, videoInfo->mDisplay.height); FallibleTArray<mp4_demuxer::Index::Indice> indices; EXPECT_TRUE(metadata.ReadTrackIndex(indices, videoInfo->mTrackId)); for (const mp4_demuxer::Index::Indice& indice : indices) { EXPECT_TRUE(indice.start_offset <= indice.end_offset); EXPECT_TRUE(indice.start_composition <= indice.end_composition); } } trackInfo = metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0); if (testFiles[test].mNumberAudioTracks == 0) { EXPECT_TRUE(!trackInfo); } else { ASSERT_TRUE(!!trackInfo); const AudioInfo* audioInfo = trackInfo->GetAsAudioInfo(); ASSERT_TRUE(!!audioInfo); EXPECT_TRUE(audioInfo->IsValid()); EXPECT_TRUE(audioInfo->IsAudio()); FallibleTArray<mp4_demuxer::Index::Indice> indices; EXPECT_TRUE(metadata.ReadTrackIndex(indices, audioInfo->mTrackId)); for (const mp4_demuxer::Index::Indice& indice : indices) { EXPECT_TRUE(indice.start_offset <= indice.end_offset); EXPECT_TRUE(indice.start_composition <= indice.end_composition); } } EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0)); EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0)); // We can see anywhere in any MPEG4. EXPECT_TRUE(metadata.CanSeek()); EXPECT_FALSE(metadata.Crypto().valid); } }
// This function assembles the system matrix and right-hand-side // for the discrete form of our wave equation. void assemble_wave(EquationSystems & es, const std::string & libmesh_dbg_var(system_name)) { // It is a good idea to make sure we are assembling // the proper system. libmesh_assert_equal_to (system_name, "Wave"); // Avoid unused variable warnings when compiling without infinite // elements enabled. libmesh_ignore(es); #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS // Get a constant reference to the mesh object. const MeshBase & mesh = es.get_mesh(); // Get a reference to the system we are solving. LinearImplicitSystem & system = es.get_system<LinearImplicitSystem>("Wave"); // A reference to the DofMap object for this system. The DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. const DofMap & dof_map = system.get_dof_map(); // The dimension that we are running. const unsigned int dim = mesh.mesh_dimension(); // Copy the speed of sound to a local variable. const Real speed = es.parameters.get<Real>("speed"); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. const FEType & fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // FEBase::build() member dynamically creates memory we will // store the object as a UniquePtr<FEBase>. UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); // Do the same for an infinite element. UniquePtr<FEBase> inf_fe (FEBase::build_InfFE(dim, fe_type)); // A 2nd order Gauss quadrature rule for numerical integration. QGauss qrule (dim, SECOND); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (&qrule); // Due to its internal structure, the infinite element handles // quadrature rules differently. It takes the quadrature // rule which has been initialized for the FE object, but // creates suitable quadrature rules by @e itself. The user // need not worry about this. inf_fe->attach_quadrature_rule (&qrule); // Define data structures to contain the element matrix // and right-hand-side vector contribution. Following // basic finite element terminology we will denote these // "Ke", "Ce", "Me", and "Fe" for the stiffness, damping // and mass matrices, and the load vector. Note that in // Acoustics, these descriptors though do @e not match the // true physical meaning of the projectors. The final // overall system, however, resembles the conventional // notation again. DenseMatrix<Number> Ke; DenseMatrix<Number> Ce; DenseMatrix<Number> Me; DenseVector<Number> Fe; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices; // Now we will loop over all the elements in the mesh. // We will compute the element matrix and right-hand-side // contribution. MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem * elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); // The mesh contains both finite and infinite elements. These // elements are handled through different classes, namely // FE and InfFE, respectively. However, since both // are derived from FEBase, they share the same interface, // and overall burden of coding is @e greatly reduced through // using a pointer, which is adjusted appropriately to the // current element type. FEBase * cfe = libmesh_nullptr; // This here is almost the only place where we need to // distinguish between finite and infinite elements. // For faster computation, however, different approaches // may be feasible. // // Up to now, we do not know what kind of element we // have. Aske the element of what type it is: if (elem->infinite()) { // We have an infinite element. Let cfe point // to our InfFE object. This is handled through // a UniquePtr. Through the UniquePtr::get() we "borrow" // the pointer, while the UniquePtr inf_fe is // still in charge of memory management. cfe = inf_fe.get(); } else { // This is a conventional finite element. Let fe handle it. cfe = fe.get(); // Boundary conditions. // Here we just zero the rhs-vector. For natural boundary // conditions check e.g. previous examples. { // Zero the RHS for this element. Fe.resize (dof_indices.size()); system.rhs->add_vector (Fe, dof_indices); } // end boundary condition section } // else if (elem->infinite()) // This is slightly different from the Poisson solver: // Since the finite element object may change, we have to // initialize the constant references to the data fields // each time again, when a new element is processed. // // The element Jacobian * quadrature weight at each integration point. const std::vector<Real> & JxW = cfe->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> > & phi = cfe->get_phi(); // The element shape function gradients evaluated at the quadrature // points. const std::vector<std::vector<RealGradient> > & dphi = cfe->get_dphi(); // The infinite elements need more data fields than conventional FE. // These are the gradients of the phase term dphase, an additional // radial weight for the test functions Sobolev_weight, and its // gradient. // // Note that these data fields are also initialized appropriately by // the FE method, so that the weak form (below) is valid for @e both // finite and infinite elements. const std::vector<RealGradient> & dphase = cfe->get_dphase(); const std::vector<Real> & weight = cfe->get_Sobolev_weight(); const std::vector<RealGradient> & dweight = cfe->get_Sobolev_dweight(); // Now this is all independent of whether we use an FE // or an InfFE. Nice, hm? ;-) // // Compute the element-specific data, as described // in previous examples. cfe->reinit (elem); // Zero the element matrices. Boundary conditions were already // processed in the FE-only section, see above. Ke.resize (dof_indices.size(), dof_indices.size()); Ce.resize (dof_indices.size(), dof_indices.size()); Me.resize (dof_indices.size(), dof_indices.size()); // The total number of quadrature points for infinite elements // @e has to be determined in a different way, compared to // conventional finite elements. This type of access is also // valid for finite elements, so this can safely be used // anytime, instead of asking the quadrature rule, as // seen in previous examples. unsigned int max_qp = cfe->n_quadrature_points(); // Loop over the quadrature points. for (unsigned int qp=0; qp<max_qp; qp++) { // Similar to the modified access to the number of quadrature // points, the number of shape functions may also be obtained // in a different manner. This offers the great advantage // of being valid for both finite and infinite elements. const unsigned int n_sf = cfe->n_shape_functions(); // Now we will build the element matrices. Since the infinite // elements are based on a Petrov-Galerkin scheme, the // resulting system matrices are non-symmetric. The additional // weight, described before, is part of the trial space. // // For the finite elements, though, these matrices are symmetric // just as we know them, since the additional fields dphase, // weight, and dweight are initialized appropriately. // // test functions: weight[qp]*phi[i][qp] // trial functions: phi[j][qp] // phase term: phase[qp] // // derivatives are similar, but note that these are of type // Point, not of type Real. for (unsigned int i=0; i<n_sf; i++) for (unsigned int j=0; j<n_sf; j++) { // (ndt*Ht + nHt*d) * nH Ke(i,j) += ( (dweight[qp] * phi[i][qp] // Point * Real = Point + // + dphi[i][qp] * weight[qp] // Point * Real = Point ) * dphi[j][qp] ) * JxW[qp]; // (d*Ht*nmut*nH - ndt*nmu*Ht*H - d*nHt*nmu*H) Ce(i,j) += ( (dphase[qp] * dphi[j][qp]) // (Point * Point) = Real * weight[qp] * phi[i][qp] // * Real * Real = Real - // - (dweight[qp] * dphase[qp]) // (Point * Point) = Real * phi[i][qp] * phi[j][qp] // * Real * Real = Real - // - (dphi[i][qp] * dphase[qp]) // (Point * Point) = Real * weight[qp] * phi[j][qp] // * Real * Real = Real ) * JxW[qp]; // (d*Ht*H * (1 - nmut*nmu)) Me(i,j) += ( (1. - (dphase[qp] * dphase[qp])) // (Real - (Point * Point)) = Real * phi[i][qp] * phi[j][qp] * weight[qp] // * Real * Real * Real = Real ) * JxW[qp]; } // end of the matrix summation loop } // end of quadrature point loop // The element matrices are now built for this element. // Collect them in Ke, and then add them to the global matrix. // The SparseMatrix::add_matrix() member does this for us. Ke.add(1./speed , Ce); Ke.add(1./(speed*speed), Me); // If this assembly program were to be used on an adaptive mesh, // we would have to apply any hanging node constraint equations dof_map.constrain_element_matrix(Ke, dof_indices); system.matrix->add_matrix (Ke, dof_indices); } // end of element loop // Note that we have not applied any boundary conditions so far. // Here we apply a unit load at the node located at (0,0,0). { // Iterate over local nodes MeshBase::const_node_iterator nd = mesh.local_nodes_begin(); const MeshBase::const_node_iterator nd_end = mesh.local_nodes_end(); for (; nd != nd_end; ++nd) { // Get a reference to the current node. const Node & node = **nd; // Check the location of the current node. if (std::abs(node(0)) < TOLERANCE && std::abs(node(1)) < TOLERANCE && std::abs(node(2)) < TOLERANCE) { // The global number of the respective degree of freedom. unsigned int dn = node.dof_number(0,0,0); system.rhs->add (dn, 1.); } } } #else // dummy assert libmesh_assert_not_equal_to (es.get_mesh().mesh_dimension(), 1); #endif //ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS }
// The matrix assembly function to be called at each time step to // prepare for the linear solve. void assemble_stokes (EquationSystems & es, const std::string & system_name) { // It is a good idea to make sure we are assembling // the proper system. libmesh_assert_equal_to (system_name, "Navier-Stokes"); // Get a constant reference to the mesh object. const MeshBase & mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); // Get a reference to the Stokes system object. TransientLinearImplicitSystem & navier_stokes_system = es.get_system<TransientLinearImplicitSystem> ("Navier-Stokes"); // Numeric ids corresponding to each variable in the system const unsigned int u_var = navier_stokes_system.variable_number ("u"); const unsigned int v_var = navier_stokes_system.variable_number ("v"); const unsigned int p_var = navier_stokes_system.variable_number ("p"); // Get the Finite Element type for "u". Note this will be // the same as the type for "v". FEType fe_vel_type = navier_stokes_system.variable_type(u_var); // Get the Finite Element type for "p". FEType fe_pres_type = navier_stokes_system.variable_type(p_var); // Build a Finite Element object of the specified type for // the velocity variables. UniquePtr<FEBase> fe_vel (FEBase::build(dim, fe_vel_type)); // Build a Finite Element object of the specified type for // the pressure variables. UniquePtr<FEBase> fe_pres (FEBase::build(dim, fe_pres_type)); // A Gauss quadrature rule for numerical integration. // Let the \p FEType object decide what order rule is appropriate. QGauss qrule (dim, fe_vel_type.default_quadrature_order()); // Tell the finite element objects to use our quadrature rule. fe_vel->attach_quadrature_rule (&qrule); fe_pres->attach_quadrature_rule (&qrule); // Here we define some references to cell-specific data that // will be used to assemble the linear system. // // The element Jacobian * quadrature weight at each integration point. const std::vector<Real> & JxW = fe_vel->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> > & phi = fe_vel->get_phi(); // The element shape function gradients for the velocity // variables evaluated at the quadrature points. const std::vector<std::vector<RealGradient> > & dphi = fe_vel->get_dphi(); // The element shape functions for the pressure variable // evaluated at the quadrature points. const std::vector<std::vector<Real> > & psi = fe_pres->get_phi(); // The value of the linear shape function gradients at the quadrature points // const std::vector<std::vector<RealGradient> > & dpsi = fe_pres->get_dphi(); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap & dof_map = navier_stokes_system.get_dof_map(); // Define data structures to contain the element matrix // and right-hand-side vector contribution. Following // basic finite element terminology we will denote these // "Ke" and "Fe". DenseMatrix<Number> Ke; DenseVector<Number> Fe; DenseSubMatrix<Number> Kuu(Ke), Kuv(Ke), Kup(Ke), Kvu(Ke), Kvv(Ke), Kvp(Ke), Kpu(Ke), Kpv(Ke), Kpp(Ke); DenseSubVector<Number> Fu(Fe), Fv(Fe), Fp(Fe); // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices; std::vector<dof_id_type> dof_indices_u; std::vector<dof_id_type> dof_indices_v; std::vector<dof_id_type> dof_indices_p; // Find out what the timestep size parameter is from the system, and // the value of theta for the theta method. We use implicit Euler (theta=1) // for this simulation even though it is only first-order accurate in time. // The reason for this decision is that the second-order Crank-Nicolson // method is notoriously oscillatory for problems with discontinuous // initial data such as the lid-driven cavity. Therefore, // we sacrifice accuracy in time for stability, but since the solution // reaches steady state relatively quickly we can afford to take small // timesteps. If you monitor the initial nonlinear residual for this // simulation, you should see that it is monotonically decreasing in time. const Real dt = es.parameters.get<Real>("dt"); const Real theta = 1.; // Now we will loop over all the elements in the mesh that // live on the local processor. We will compute the element // matrix and right-hand-side contribution. Since the mesh // will be refined we want to only consider the ACTIVE elements, // hence we use a variant of the \p active_elem_iterator. MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem * elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); dof_map.dof_indices (elem, dof_indices_u, u_var); dof_map.dof_indices (elem, dof_indices_v, v_var); dof_map.dof_indices (elem, dof_indices_p, p_var); const unsigned int n_dofs = dof_indices.size(); const unsigned int n_u_dofs = dof_indices_u.size(); const unsigned int n_v_dofs = dof_indices_v.size(); const unsigned int n_p_dofs = dof_indices_p.size(); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe_vel->reinit (elem); fe_pres->reinit (elem); // Zero the element matrix and right-hand side before // summing them. We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); // Reposition the submatrices... The idea is this: // // - - - - // | Kuu Kuv Kup | | Fu | // Ke = | Kvu Kvv Kvp |; Fe = | Fv | // | Kpu Kpv Kpp | | Fp | // - - - - // // The \p DenseSubMatrix.repostition () member takes the // (row_offset, column_offset, row_size, column_size). // // Similarly, the \p DenseSubVector.reposition () member // takes the (row_offset, row_size) Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs); Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs); Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs); Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs); Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs); Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs); Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs); Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs); Kpp.reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs); Fu.reposition (u_var*n_u_dofs, n_u_dofs); Fv.reposition (v_var*n_u_dofs, n_v_dofs); Fp.reposition (p_var*n_u_dofs, n_p_dofs); // Now we will build the element matrix and right-hand-side. // Constructing the RHS requires the solution and its // gradient from the previous timestep. This must be // calculated at each quadrature point by summing the // solution degree-of-freedom values by the appropriate // weight functions. for (unsigned int qp=0; qp<qrule.n_points(); qp++) { // Values to hold the solution & its gradient at the previous timestep. Number u = 0., u_old = 0.; Number v = 0., v_old = 0.; Number p_old = 0.; Gradient grad_u, grad_u_old; Gradient grad_v, grad_v_old; // Compute the velocity & its gradient from the previous timestep // and the old Newton iterate. for (unsigned int l=0; l<n_u_dofs; l++) { // From the old timestep: u_old += phi[l][qp]*navier_stokes_system.old_solution (dof_indices_u[l]); v_old += phi[l][qp]*navier_stokes_system.old_solution (dof_indices_v[l]); grad_u_old.add_scaled (dphi[l][qp],navier_stokes_system.old_solution (dof_indices_u[l])); grad_v_old.add_scaled (dphi[l][qp],navier_stokes_system.old_solution (dof_indices_v[l])); // From the previous Newton iterate: u += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_u[l]); v += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_v[l]); grad_u.add_scaled (dphi[l][qp],navier_stokes_system.current_solution (dof_indices_u[l])); grad_v.add_scaled (dphi[l][qp],navier_stokes_system.current_solution (dof_indices_v[l])); } // Compute the old pressure value at this quadrature point. for (unsigned int l=0; l<n_p_dofs; l++) p_old += psi[l][qp]*navier_stokes_system.old_solution (dof_indices_p[l]); // Definitions for convenience. It is sometimes simpler to do a // dot product if you have the full vector at your disposal. const NumberVectorValue U_old (u_old, v_old); const NumberVectorValue U (u, v); const Number u_x = grad_u(0); const Number u_y = grad_u(1); const Number v_x = grad_v(0); const Number v_y = grad_v(1); // First, an i-loop over the velocity degrees of freedom. // We know that n_u_dofs == n_v_dofs so we can compute contributions // for both at the same time. for (unsigned int i=0; i<n_u_dofs; i++) { Fu(i) += JxW[qp]*(u_old*phi[i][qp] - // mass-matrix term (1.-theta)*dt*(U_old*grad_u_old)*phi[i][qp] + // convection term (1.-theta)*dt*p_old*dphi[i][qp](0) - // pressure term on rhs (1.-theta)*dt*(grad_u_old*dphi[i][qp]) + // diffusion term on rhs theta*dt*(U*grad_u)*phi[i][qp]); // Newton term Fv(i) += JxW[qp]*(v_old*phi[i][qp] - // mass-matrix term (1.-theta)*dt*(U_old*grad_v_old)*phi[i][qp] + // convection term (1.-theta)*dt*p_old*dphi[i][qp](1) - // pressure term on rhs (1.-theta)*dt*(grad_v_old*dphi[i][qp]) + // diffusion term on rhs theta*dt*(U*grad_v)*phi[i][qp]); // Newton term // Note that the Fp block is identically zero unless we are using // some kind of artificial compressibility scheme... // Matrix contributions for the uu and vv couplings. for (unsigned int j=0; j<n_u_dofs; j++) { Kuu(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] + // mass matrix term theta*dt*(dphi[i][qp]*dphi[j][qp]) + // diffusion term theta*dt*(U*dphi[j][qp])*phi[i][qp] + // convection term theta*dt*u_x*phi[i][qp]*phi[j][qp]); // Newton term Kuv(i,j) += JxW[qp]*theta*dt*u_y*phi[i][qp]*phi[j][qp]; // Newton term Kvv(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] + // mass matrix term theta*dt*(dphi[i][qp]*dphi[j][qp]) + // diffusion term theta*dt*(U*dphi[j][qp])*phi[i][qp] + // convection term theta*dt*v_y*phi[i][qp]*phi[j][qp]); // Newton term Kvu(i,j) += JxW[qp]*theta*dt*v_x*phi[i][qp]*phi[j][qp]; // Newton term } // Matrix contributions for the up and vp couplings. for (unsigned int j=0; j<n_p_dofs; j++) { Kup(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](0)); Kvp(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](1)); } } // Now an i-loop over the pressure degrees of freedom. This code computes // the matrix entries due to the continuity equation. Note: To maintain a // symmetric matrix, we may (or may not) multiply the continuity equation by // negative one. Here we do not. for (unsigned int i=0; i<n_p_dofs; i++) for (unsigned int j=0; j<n_u_dofs; j++) { Kpu(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](0); Kpv(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](1); } } // end of the quadrature point qp-loop // At this point the interior element integration has // been completed. However, we have not yet addressed // boundary conditions. For this example we will only // consider simple Dirichlet boundary conditions imposed // via the penalty method. The penalty method used here // is equivalent (for Lagrange basis functions) to lumping // the matrix resulting from the L2 projection penalty // approach introduced in example 3. { // The penalty value. \f$ \frac{1}{\epsilon} \f$ const Real penalty = 1.e10; // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. for (unsigned int s=0; s<elem->n_sides(); s++) if (elem->neighbor(s) == libmesh_nullptr) { UniquePtr<Elem> side (elem->build_side(s)); // Loop over the nodes on the side. for (unsigned int ns=0; ns<side->n_nodes(); ns++) { // Boundary ids are set internally by // build_square(). // 0=bottom // 1=right // 2=top // 3=left // Set u = 1 on the top boundary, 0 everywhere else const Real u_value = (mesh.get_boundary_info().has_boundary_id(elem, s, 2)) ? 1. : 0.; // Set v = 0 everywhere const Real v_value = 0.; // Find the node on the element matching this node on // the side. That defined where in the element matrix // the boundary condition will be applied. for (unsigned int n=0; n<elem->n_nodes(); n++) if (elem->node(n) == side->node(ns)) { // Matrix contribution. Kuu(n,n) += penalty; Kvv(n,n) += penalty; // Right-hand-side contribution. Fu(n) += penalty*u_value; Fv(n) += penalty*v_value; } } // end face node loop } // end if (elem->neighbor(side) == libmesh_nullptr) // Pin the pressure to zero at global node number "pressure_node". // This effectively removes the non-trivial null space of constant // pressure solutions. const bool pin_pressure = true; if (pin_pressure) { const unsigned int pressure_node = 0; const Real p_value = 0.0; for (unsigned int c=0; c<elem->n_nodes(); c++) if (elem->node(c) == pressure_node) { Kpp(c,c) += penalty; Fp(c) += penalty*p_value; } } } // end boundary condition section // If this assembly program were to be used on an adaptive mesh, // we would have to apply any hanging node constraint equations dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); // The element matrix and right-hand-side are now built // for this element. Add them to the global matrix and // right-hand-side vector. The \p SparseMatrix::add_matrix() // and \p NumericVector::add_vector() members do this for us. navier_stokes_system.matrix->add_matrix (Ke, dof_indices); navier_stokes_system.rhs->add_vector (Fe, dof_indices); } // end of element loop }
void TestInvalidateExpiredCacheEntry() { _PrefixArray array = { GeneratePrefix(CACHED_URL, 10), GeneratePrefix(NEG_CACHE_EXPIRED_URL, 8), GeneratePrefix(POS_CACHE_EXPIRED_URL, 5), GeneratePrefix(BOTH_CACHE_EXPIRED_URL, 4) }; UniquePtr<T> cache = SetupLookupCache<T>(array); SetupCacheEntry(cache.get(), CACHED_URL, false, false); SetupCacheEntry(cache.get(), NEG_CACHE_EXPIRED_URL, true, false); SetupCacheEntry(cache.get(), POS_CACHE_EXPIRED_URL, false, true); SetupCacheEntry(cache.get(), BOTH_CACHE_EXPIRED_URL, true, true); // Before invalidate TestCache<T>(CACHED_URL, true, true, true, cache.get()); TestCache<T>(NEG_CACHE_EXPIRED_URL, true, true, true, cache.get()); TestCache<T>(POS_CACHE_EXPIRED_URL, true, false, true, cache.get()); TestCache<T>(BOTH_CACHE_EXPIRED_URL, true, false, true, cache.get()); // Call InvalidateExpiredCacheEntry to remove cache entries whose negative cache // time is expired cache->InvalidateExpiredCacheEntries(); // After invalidate, NEG_CACHE_EXPIRED_URL & BOTH_CACHE_EXPIRED_URL should // not be found in cache. TestCache<T>(NEG_CACHE_EXPIRED_URL, true, false, false, cache.get()); TestCache<T>(BOTH_CACHE_EXPIRED_URL, true, false, false, cache.get()); // Other entries should remain the same result. TestCache<T>(CACHED_URL, true, true, true, cache.get()); TestCache<T>(POS_CACHE_EXPIRED_URL, true, false, true, cache.get()); }
// Jacobian assembly function for the Laplace-Young system void LaplaceYoung::jacobian (const NumericVector<Number>& soln, SparseMatrix<Number>& jacobian, NonlinearImplicitSystem& sys) { // Get a reference to the equation system. EquationSystems &es = sys.get_equation_systems(); // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); // Get a reference to the NonlinearImplicitSystem we are solving NonlinearImplicitSystem& system = es.get_system<NonlinearImplicitSystem>("Laplace-Young"); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = system.get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p UniquePtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); // A 5th order Gauss quadrature rule for numerical integration. QGauss qrule (dim, FIFTH); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (&qrule); // Here we define some references to cell-specific data that // will be used to assemble the linear system. // We begin with the element Jacobian * quadrature weight at each // integration point. const std::vector<Real>& JxW = fe->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> >& phi = fe->get_phi(); // The element shape function gradients evaluated at the quadrature // points. const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // Define data structures to contain the Jacobian element matrix. // Following basic finite element terminology we will denote these // "Ke". More detail is in example 3. DenseMatrix<Number> Ke; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices; // Now we will loop over all the active elements in the mesh which // are local to this processor. // We will compute the element Jacobian contribution. MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe->reinit (elem); // Zero the element Jacobian before // summing them. We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Ke.resize (dof_indices.size(), dof_indices.size()); // Now we will build the element Jacobian. This involves // a double loop to integrate the test funcions (i) against // the trial functions (j). Note that the Jacobian depends // on the current solution x, which we access using the soln // vector. // for (unsigned int qp=0; qp<qrule.n_points(); qp++) { Gradient grad_u; for (unsigned int i=0; i<phi.size(); i++) grad_u += dphi[i][qp]*soln(dof_indices[i]); const Number sa = 1. + grad_u*grad_u, K = 1. / std::sqrt(sa), dK = -K / sa; for (unsigned int i=0; i<phi.size(); i++) for (unsigned int j=0; j<phi.size(); j++) Ke(i,j) += JxW[qp]*( K * (dphi[i][qp]*dphi[j][qp]) + dK * (grad_u*dphi[j][qp]) * (grad_u*dphi[i][qp]) + _kappa * phi[i][qp] * phi[j][qp] ); } dof_map.constrain_element_matrix (Ke, dof_indices); // Add the element matrix to the system Jacobian. jacobian.add_matrix (Ke, dof_indices); } // That's it. }
// Residual assembly function for the Laplace-Young system void LaplaceYoung::residual (const NumericVector<Number>& soln, NumericVector<Number>& residual, NonlinearImplicitSystem& sys) { EquationSystems &es = sys.get_equation_systems(); // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); libmesh_assert_equal_to (dim, 2); // Get a reference to the NonlinearImplicitSystem we are solving NonlinearImplicitSystem& system = es.get_system<NonlinearImplicitSystem>("Laplace-Young"); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = system.get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p UniquePtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); // A 5th order Gauss quadrature rule for numerical integration. QGauss qrule (dim, FIFTH); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (&qrule); // Declare a special finite element object for // boundary integration. UniquePtr<FEBase> fe_face (FEBase::build(dim, fe_type)); // Boundary integration requires one quadraure rule, // with dimensionality one less than the dimensionality // of the element. QGauss qface(dim-1, FIFTH); // Tell the finte element object to use our // quadrature rule. fe_face->attach_quadrature_rule (&qface); // Here we define some references to cell-specific data that // will be used to assemble the linear system. // We begin with the element Jacobian * quadrature weight at each // integration point. const std::vector<Real>& JxW = fe->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> >& phi = fe->get_phi(); // The element shape function gradients evaluated at the quadrature // points. const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // Define data structures to contain the resdual contributions DenseVector<Number> Re; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices; // Now we will loop over all the active elements in the mesh which // are local to this processor. // We will compute the element residual. residual.zero(); MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe->reinit (elem); // We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Re.resize (dof_indices.size()); // Now we will build the residual. This involves // the construction of the matrix K and multiplication of it // with the current solution x. We rearrange this into two loops: // In the first, we calculate only the contribution of // K_ij*x_j which is independent of the row i. In the second loops, // we multiply with the row-dependent part and add it to the element // residual. for (unsigned int qp=0; qp<qrule.n_points(); qp++) { Number u = 0; Gradient grad_u; for (unsigned int j=0; j<phi.size(); j++) { u += phi[j][qp]*soln(dof_indices[j]); grad_u += dphi[j][qp]*soln(dof_indices[j]); } const Number K = 1./std::sqrt(1. + grad_u*grad_u); for (unsigned int i=0; i<phi.size(); i++) Re(i) += JxW[qp]*( K*(dphi[i][qp]*grad_u) + _kappa*phi[i][qp]*u ); } // At this point the interior element integration has // been completed. However, we have not yet addressed // boundary conditions. // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. for (unsigned int side=0; side<elem->n_sides(); side++) if (elem->neighbor(side) == NULL) { // The value of the shape functions at the quadrature // points. const std::vector<std::vector<Real> >& phi_face = fe_face->get_phi(); // The Jacobian * Quadrature Weight at the quadrature // points on the face. const std::vector<Real>& JxW_face = fe_face->get_JxW(); // Compute the shape function values on the element face. fe_face->reinit(elem, side); // Loop over the face quadrature points for integration. for (unsigned int qp=0; qp<qface.n_points(); qp++) { // This is the right-hand-side contribution (f), // which has to be subtracted from the current residual for (unsigned int i=0; i<phi_face.size(); i++) Re(i) -= JxW_face[qp]*_sigma*phi_face[i][qp]; } } dof_map.constrain_element_vector (Re, dof_indices); residual.add_vector (Re, dof_indices); } // That's it. }
// Post-process the solution to compute stresses void compute_stresses() { const MeshBase& mesh = es.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); LinearImplicitSystem& system = es.get_system<LinearImplicitSystem>("Elasticity"); unsigned int displacement_vars[3]; displacement_vars[0] = system.variable_number ("u"); displacement_vars[1] = system.variable_number ("v"); displacement_vars[2] = system.variable_number ("w"); const unsigned int u_var = system.variable_number ("u"); const DofMap& dof_map = system.get_dof_map(); FEType fe_type = dof_map.variable_type(u_var); UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); QGauss qrule (dim, fe_type.default_quadrature_order()); fe->attach_quadrature_rule (&qrule); const std::vector<Real>& JxW = fe->get_JxW(); const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // Also, get a reference to the ExplicitSystem ExplicitSystem& stress_system = es.get_system<ExplicitSystem>("StressSystem"); const DofMap& stress_dof_map = stress_system.get_dof_map(); unsigned int sigma_vars[6]; sigma_vars[0] = stress_system.variable_number ("sigma_00"); sigma_vars[1] = stress_system.variable_number ("sigma_01"); sigma_vars[2] = stress_system.variable_number ("sigma_02"); sigma_vars[3] = stress_system.variable_number ("sigma_11"); sigma_vars[4] = stress_system.variable_number ("sigma_12"); sigma_vars[5] = stress_system.variable_number ("sigma_22"); unsigned int vonMises_var = stress_system.variable_number ("vonMises"); // Storage for the stress dof indices on each element std::vector< std::vector<dof_id_type> > dof_indices_var(system.n_vars()); std::vector<dof_id_type> stress_dof_indices_var; // To store the stress tensor on each element DenseMatrix<Number> elem_avg_stress_tensor(3,3); MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { const Elem* elem = *el; for(unsigned int var=0; var<3; var++) { dof_map.dof_indices (elem, dof_indices_var[var], displacement_vars[var]); } const unsigned int n_var_dofs = dof_indices_var[0].size(); fe->reinit (elem); // clear the stress tensor elem_avg_stress_tensor.resize(3,3); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { DenseMatrix<Number> grad_u(3,3); for(unsigned int var_i=0; var_i<3; var_i++) for(unsigned int var_j=0; var_j<3; var_j++) { for (unsigned int j=0; j<n_var_dofs; j++) { // Row is variable u1, u2, or u3, column is x, y, or z grad_u(var_i,var_j) += dphi[j][qp](var_j)* system.current_solution(dof_indices_var[var_i][j]); } } DenseMatrix<Number> stress_tensor(3,3); for(unsigned int i=0; i<3; i++) for(unsigned int j=0; j<3; j++) for(unsigned int k=0; k<3; k++) for(unsigned int l=0; l<3; l++) { stress_tensor(i,j) += elasticity_tensor(i,j,k,l) * grad_u(k,l); } // stress_tensor now holds the stress at point qp. // We want to plot the average stress on each element, hence // we integrate stress_tensor elem_avg_stress_tensor.add(JxW[qp], stress_tensor); } // Get the average stress per element by dividing by volume elem_avg_stress_tensor.scale(1./elem->volume()); // load elem_sigma data into stress_system unsigned int stress_var_index = 0; for(unsigned int i=0; i<3; i++) for(unsigned int j=i; j<3; j++) { stress_dof_map.dof_indices (elem, stress_dof_indices_var, sigma_vars[stress_var_index]); // We are using CONSTANT MONOMIAL basis functions, hence we only need to get // one dof index per variable dof_id_type dof_index = stress_dof_indices_var[0]; if( (stress_system.solution->first_local_index() <= dof_index) && (dof_index < stress_system.solution->last_local_index()) ) { stress_system.solution->set(dof_index, elem_avg_stress_tensor(i,j)); } stress_var_index++; } // Also, the von Mises stress Number vonMises_value = std::sqrt( 0.5*( pow(elem_avg_stress_tensor(0,0) - elem_avg_stress_tensor(1,1),2.) + pow(elem_avg_stress_tensor(1,1) - elem_avg_stress_tensor(2,2),2.) + pow(elem_avg_stress_tensor(2,2) - elem_avg_stress_tensor(0,0),2.) + 6.*(pow(elem_avg_stress_tensor(0,1),2.) + pow(elem_avg_stress_tensor(1,2),2.) + pow(elem_avg_stress_tensor(2,0),2.)) ) ); stress_dof_map.dof_indices (elem, stress_dof_indices_var, vonMises_var); dof_id_type dof_index = stress_dof_indices_var[0]; if( (stress_system.solution->first_local_index() <= dof_index) && (dof_index < stress_system.solution->last_local_index()) ) { stress_system.solution->set(dof_index, vonMises_value); } } // Should call close and update when we set vector entries directly stress_system.solution->close(); stress_system.update(); }
void LaplaceMeshSmoother::init() { switch (_mesh.mesh_dimension()) { // TODO:[BSK] Fix this to work for refined meshes... I think // the implementation was done quickly for Damien, who did not have // refined grids. Fix it here and in the original Mesh member. case 2: // Stolen directly from build_L_graph in mesh_base.C { // Initialize space in the graph. It is indexed by node id. // Each node may be connected to an arbitrary number of other // nodes via edges. _graph.resize(_mesh.max_node_id()); MeshBase::element_iterator el = _mesh.active_local_elements_begin(); const MeshBase::element_iterator end = _mesh.active_local_elements_end(); for (; el != end; ++el) { // Constant handle for the element const Elem * elem = *el; for (unsigned int s=0; s<elem->n_neighbors(); s++) { // Only operate on sides which are on the // boundary or for which the current element's // id is greater than its neighbor's. // Sides get only built once. if ((elem->neighbor(s) == libmesh_nullptr) || (elem->id() > elem->neighbor(s)->id())) { UniquePtr<Elem> side(elem->build_side(s)); _graph[side->node_id(0)].push_back(side->node_id(1)); _graph[side->node_id(1)].push_back(side->node_id(0)); } } } _initialized = true; break; } // case 2 case 3: // Stolen blatantly from build_L_graph in mesh_base.C { // Initialize space in the graph. _graph.resize(_mesh.max_node_id()); MeshBase::element_iterator el = _mesh.active_local_elements_begin(); const MeshBase::element_iterator end = _mesh.active_local_elements_end(); for (; el != end; ++el) { // Shortcut notation for simplicity const Elem * elem = *el; for (unsigned int f=0; f<elem->n_neighbors(); f++) // Loop over faces if ((elem->neighbor(f) == libmesh_nullptr) || (elem->id() > elem->neighbor(f)->id())) { // We need a full (i.e. non-proxy) element for the face, since we will // be looking at its sides as well! UniquePtr<Elem> face = elem->build_side(f, /*proxy=*/false); for (unsigned int s=0; s<face->n_neighbors(); s++) // Loop over face's edges { // Here we can use a proxy UniquePtr<Elem> side = face->build_side(s); // At this point, we just insert the node numbers // again. At the end we'll call sort and unique // to make sure there are no duplicates _graph[side->node_id(0)].push_back(side->node_id(1)); _graph[side->node_id(1)].push_back(side->node_id(0)); } } } _initialized = true; break; } // case 3 default: libmesh_error_msg("At this time it is not possible to smooth a dimension " << _mesh.mesh_dimension() << "mesh. Aborting..."); } // Done building graph from local elements. Let's now allgather the // graph so that it is available on all processors for the actual // smoothing operation? this->allgather_graph(); // In 3D, it's possible for > 2 processor partitions to meet // at a single edge, while in 2D only 2 processor partitions // share an edge. Therefore the allgather'd graph in 3D may // now have duplicate entries and we need to remove them so // they don't foul up the averaging algorithm employed by the // Laplace smoother. for (unsigned i=0; i<_graph.size(); ++i) { // The std::unique algorithm removes duplicate *consecutive* elements from a range, // so it only makes sense to call it on a sorted range... std::sort(_graph[i].begin(), _graph[i].end()); _graph[i].erase(std::unique(_graph[i].begin(), _graph[i].end()), _graph[i].end()); } } // init()
void DivaIO::write_stream (std::ostream & out_file) { /* From Kelly: ([email protected]) Ok, the following is the format: #points #triangles #quads #tets #prisms #pyramids #hexs loop over all points (written out x y z x y z ...) loop over all triangles (written out i1 i2 i3) (These are indices into the points going from 1 to #points) loop over all quads (written out i1 i2 i3 i4) (Same numbering scheme) loop over all triangles and quads (write out b1) (This is a boundary condition for each triangle and each hex. You can put anything you want here) loop over all tets (written out i1 i2 i3 i4) (Same) loop over all pyramids (written out i1 i2 i3 i4 i5) (Same) loop over all prisms (written out i1 i2 i3 i4 i5 i6) (Same) loop over all hexs (written out i1 i2 i3 i4 i5 i6 i7 i8) (Same) */ // Be sure the stream has been created successfully. libmesh_assert (out_file.good()); // Can't use a constant mesh reference since we have to // sync the boundary info. libmesh_here(); libMesh::err << "WARNING... Sure you want to do this?" << std::endl; MeshBase & the_mesh = const_cast<MeshBase &> (MeshOutput<MeshBase>::mesh()); if (the_mesh.mesh_dimension() < 3) { libMesh::err << "WARNING: DIVA only supports 3D meshes.\n\n" << "Exiting without producing output.\n"; return; } BoundaryMesh boundary_mesh (the_mesh.comm(), cast_int<unsigned char>(the_mesh.mesh_dimension()-1)); the_mesh.get_boundary_info().sync(boundary_mesh); /** * Write the header */ out_file << the_mesh.n_nodes() << ' ' << (MeshTools::n_active_elem_of_type(boundary_mesh,TRI3) + MeshTools::n_active_elem_of_type(boundary_mesh,TRI6)*4) << ' ' << (MeshTools::n_active_elem_of_type(boundary_mesh, QUAD4) + MeshTools::n_active_elem_of_type(boundary_mesh, QUAD8) + MeshTools::n_active_elem_of_type(boundary_mesh, QUAD9)*4) << ' ' << (MeshTools::n_active_elem_of_type(the_mesh, TET4) + MeshTools::n_active_elem_of_type(the_mesh, TET10)*8) << ' ' << MeshTools::n_active_elem_of_type(the_mesh, PYRAMID5) << ' ' << (MeshTools::n_active_elem_of_type(the_mesh, PRISM6) + MeshTools::n_active_elem_of_type(the_mesh, PRISM18)*8) << ' ' << (MeshTools::n_active_elem_of_type(the_mesh, HEX8) + MeshTools::n_active_elem_of_type(the_mesh, HEX20) + MeshTools::n_active_elem_of_type(the_mesh, HEX27)*8) << ' ' << '\n'; boundary_mesh.clear(); /** * Write the nodes */ for (unsigned int v=0; v<the_mesh.n_nodes(); v++) the_mesh.point(v).write_unformatted(out_file); /** * Write the BC faces */ { /** * Write the triangles */ for(unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) for (unsigned int s=0; s<the_mesh.elem(e)->n_sides(); s++) if (the_mesh.elem(e)->neighbor(s) == libmesh_nullptr) { const UniquePtr<Elem> side(the_mesh.elem(e)->build_side(s)); if (side->type() == TRI3) { out_file << side->node(0)+1 << " " << side->node(1)+1 << " " << side->node(2)+1 << '\n'; } else if (side->type() == TRI6) { out_file << side->node(0)+1 << " " << side->node(3)+1 << " " << side->node(5)+1 << '\n' << side->node(3)+1 << " " << side->node(1)+1 << " " << side->node(4)+1 << '\n' << side->node(5)+1 << " " << side->node(4)+1 << " " << side->node(2)+1 << '\n' << side->node(3)+1 << " " << side->node(4)+1 << " " << side->node(5)+1 << '\n'; } } /** * Write the quadrilaterals */ for(unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) for (unsigned int s=0; s<the_mesh.elem(e)->n_sides(); s++) if (the_mesh.elem(e)->neighbor(s) == libmesh_nullptr) { const UniquePtr<Elem> side(the_mesh.elem(e)->build_side(s)); if ((side->type() == QUAD4) || (side->type() == QUAD8) ) { out_file << side->node(0)+1 << " " << side->node(1)+1 << " " << side->node(2)+1 << " " << side->node(3)+1 << '\n'; } else if (side->type() == QUAD9) { out_file << side->node(0)+1 << " " << side->node(4)+1 << " " << side->node(8)+1 << " " << side->node(7)+1 << '\n' << side->node(4)+1 << " " << side->node(1)+1 << " " << side->node(5)+1 << " " << side->node(8)+1 << '\n' << side->node(7)+1 << " " << side->node(8)+1 << " " << side->node(6)+1 << " " << side->node(3)+1 << '\n' << side->node(8)+1 << " " << side->node(5)+1 << " " << side->node(2)+1 << " " << side->node(6)+1 << '\n'; } } } /** * Write the BC IDs */ { /** * Write the triangles */ for(unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) for (unsigned short s=0; s<the_mesh.elem(e)->n_sides(); s++) if (the_mesh.elem(e)->neighbor(s) == libmesh_nullptr) { const UniquePtr<Elem> side(the_mesh.elem(e)->build_side(s)); if ((side->type() == TRI3) || (side->type() == TRI6) ) out_file << the_mesh.get_boundary_info().boundary_id(the_mesh.elem(e), s) << '\n'; } /** * Write the quadrilaterals */ for(unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) for (unsigned short s=0; s<the_mesh.elem(e)->n_sides(); s++) if (the_mesh.elem(e)->neighbor(s) == libmesh_nullptr) { const UniquePtr<Elem> side(the_mesh.elem(e)->build_side(s)); if ((side->type() == QUAD4) || (side->type() == QUAD8) || (side->type() == QUAD9)) out_file << the_mesh.get_boundary_info().boundary_id(the_mesh.elem(e), s); } } /** * Write all the Tets */ for (unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) { if (the_mesh.elem(e)->type() == TET4) { out_file << the_mesh.elem(e)->node(0)+1 << " " << the_mesh.elem(e)->node(1)+1 << " " << the_mesh.elem(e)->node(2)+1 << " " << the_mesh.elem(e)->node(3)+1 << '\n'; } else if (the_mesh.elem(e)->type() == TET10) { out_file << the_mesh.elem(e)->node(0)+1 << " " << the_mesh.elem(e)->node(4)+1 << " " << the_mesh.elem(e)->node(6)+1 << " " << the_mesh.elem(e)->node(7)+1 << '\n'; out_file << the_mesh.elem(e)->node(4)+1 << " " << the_mesh.elem(e)->node(1)+1 << " " << the_mesh.elem(e)->node(5)+1 << " " << the_mesh.elem(e)->node(8)+1 << '\n'; out_file << the_mesh.elem(e)->node(6)+1 << " " << the_mesh.elem(e)->node(5)+1 << " " << the_mesh.elem(e)->node(2)+1 << " " << the_mesh.elem(e)->node(9)+1 << '\n'; out_file << the_mesh.elem(e)->node(7)+1 << " " << the_mesh.elem(e)->node(8)+1 << " " << the_mesh.elem(e)->node(9)+1 << " " << the_mesh.elem(e)->node(3)+1 << '\n'; out_file << the_mesh.elem(e)->node(4)+1 << " " << the_mesh.elem(e)->node(8)+1 << " " << the_mesh.elem(e)->node(6)+1 << " " << the_mesh.elem(e)->node(7)+1 << '\n'; out_file << the_mesh.elem(e)->node(4)+1 << " " << the_mesh.elem(e)->node(5)+1 << " " << the_mesh.elem(e)->node(6)+1 << " " << the_mesh.elem(e)->node(8)+1 << '\n'; out_file << the_mesh.elem(e)->node(6)+1 << " " << the_mesh.elem(e)->node(5)+1 << " " << the_mesh.elem(e)->node(9)+1 << " " << the_mesh.elem(e)->node(8)+1 << '\n'; out_file << the_mesh.elem(e)->node(6)+1 << " " << the_mesh.elem(e)->node(8)+1 << " " << the_mesh.elem(e)->node(9)+1 << " " << the_mesh.elem(e)->node(7)+1 << '\n'; } } /** * Write all the Pyramids */ for (unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) if (the_mesh.elem(e)->type() == PYRAMID5) { out_file << the_mesh.elem(e)->node(0)+1 << " " << the_mesh.elem(e)->node(1)+1 << " " << the_mesh.elem(e)->node(2)+1 << " " << the_mesh.elem(e)->node(3)+1 << " " << the_mesh.elem(e)->node(4)+1 << '\n'; } /** * Write all the Prisms */ for (unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) { if (the_mesh.elem(e)->type() == PRISM6) { out_file << the_mesh.elem(e)->node(0)+1 << " " << the_mesh.elem(e)->node(1)+1 << " " << the_mesh.elem(e)->node(2)+1 << " " << the_mesh.elem(e)->node(3)+1 << " " << the_mesh.elem(e)->node(4)+1 << " " << the_mesh.elem(e)->node(5)+1 << '\n'; } else if (the_mesh.elem(e)->type() == PRISM18) libmesh_error_msg("PRISM18 element type not supported."); } /** * Write all the Hexes */ for (unsigned int e=0; e<the_mesh.n_elem(); e++) if (the_mesh.elem(e)->active()) if ((the_mesh.elem(e)->type() == HEX8) || (the_mesh.elem(e)->type() == HEX20) || (the_mesh.elem(e)->type() == HEX27) ) { std::vector<dof_id_type> conn; for (unsigned int se=0; se<the_mesh.elem(e)->n_sub_elem(); se++) { the_mesh.elem(e)->connectivity(se, TECPLOT, conn); out_file << conn[0] << ' ' << conn[1] << ' ' << conn[2] << ' ' << conn[3] << ' ' << conn[4] << ' ' << conn[5] << ' ' << conn[6] << ' ' << conn[7] << '\n'; } } }
nsresult TestWriteObject() { nsresult rv; nsCOMPtr<nsIURI> obj = do_CreateInstance("@mozilla.org/network/simple-uri;1"); if (!obj) { fail("did not create object in test write object"); return NS_ERROR_UNEXPECTED; } NS_NAMED_LITERAL_CSTRING(spec, "http://www.mozilla.org"); obj->SetSpec(spec); nsCOMPtr<nsIStartupCache> sc = do_GetService("@mozilla.org/startupcache/cache;1", &rv); sc->InvalidateCache(); // Create an object stream. Usually this is done with // NewObjectOutputWrappedStorageStream, but that uses // StartupCache::GetSingleton in debug builds, and we // don't have access to that here. Obviously. const char* id = "id"; nsCOMPtr<nsIStorageStream> storageStream = do_CreateInstance("@mozilla.org/storagestream;1"); NS_ENSURE_ARG_POINTER(storageStream); rv = storageStream->Init(256, (uint32_t) -1); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIObjectOutputStream> objectOutput = do_CreateInstance("@mozilla.org/binaryoutputstream;1"); if (!objectOutput) return NS_ERROR_OUT_OF_MEMORY; nsCOMPtr<nsIOutputStream> outputStream = do_QueryInterface(storageStream); rv = objectOutput->SetOutputStream(outputStream); if (NS_FAILED(rv)) { fail("failed to create output stream"); return rv; } nsCOMPtr<nsISupports> objQI(do_QueryInterface(obj)); rv = objectOutput->WriteObject(objQI, true); if (NS_FAILED(rv)) { fail("failed to write object"); return rv; } UniquePtr<char[]> buf; uint32_t len; NewBufferFromStorageStream(storageStream, &buf, &len); // Since this is a post-startup write, it should be written and // available. rv = sc->PutBuffer(id, buf.get(), len); if (NS_FAILED(rv)) { fail("failed to insert input stream"); return rv; } UniquePtr<char[]> buf2; uint32_t len2; nsCOMPtr<nsIObjectInputStream> objectInput; rv = sc->GetBuffer(id, &buf2, &len2); if (NS_FAILED(rv)) { fail("failed to retrieve buffer"); return rv; } rv = NewObjectInputStreamFromBuffer(Move(buf2), len2, getter_AddRefs(objectInput)); if (NS_FAILED(rv)) { fail("failed to created input stream"); return rv; } nsCOMPtr<nsISupports> deserialized; rv = objectInput->ReadObject(true, getter_AddRefs(deserialized)); if (NS_FAILED(rv)) { fail("failed to read object"); return rv; } bool match = false; nsCOMPtr<nsIURI> uri(do_QueryInterface(deserialized)); if (uri) { nsCString outSpec; uri->GetSpec(outSpec); match = outSpec.Equals(spec); } if (!match) { fail("deserialized object has incorrect information"); return rv; } passed("write object"); return NS_OK; }
nsresult nsWindowGfx::CreateIcon(imgIContainer *aContainer, bool aIsCursor, uint32_t aHotspotX, uint32_t aHotspotY, IntSize aScaledSize, HICON *aIcon) { MOZ_ASSERT((aScaledSize.width > 0 && aScaledSize.height > 0) || (aScaledSize.width == 0 && aScaledSize.height == 0)); // Get the image data RefPtr<SourceSurface> surface = aContainer->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); NS_ENSURE_TRUE(surface, NS_ERROR_NOT_AVAILABLE); IntSize frameSize = surface->GetSize(); if (frameSize.IsEmpty()) { return NS_ERROR_FAILURE; } IntSize iconSize(aScaledSize.width, aScaledSize.height); if (iconSize == IntSize(0, 0)) { // use frame's intrinsic size iconSize = frameSize; } RefPtr<DataSourceSurface> dataSurface; bool mappedOK; DataSourceSurface::MappedSurface map; if (iconSize != frameSize) { // Scale the surface dataSurface = Factory::CreateDataSourceSurface(iconSize, SurfaceFormat::B8G8R8A8); NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map); NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE); RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(BackendType::CAIRO, map.mData, dataSurface->GetSize(), map.mStride, SurfaceFormat::B8G8R8A8); if (!dt) { gfxWarning() << "nsWindowGfx::CreatesIcon failed in CreateDrawTargetForData"; return NS_ERROR_OUT_OF_MEMORY; } dt->DrawSurface(surface, Rect(0, 0, iconSize.width, iconSize.height), Rect(0, 0, frameSize.width, frameSize.height), DrawSurfaceOptions(), DrawOptions(1.0f, CompositionOp::OP_SOURCE)); } else if (surface->GetFormat() != SurfaceFormat::B8G8R8A8) { // Convert format to SurfaceFormat::B8G8R8A8 dataSurface = gfxUtils:: CopySurfaceToDataSourceSurfaceWithFormat(surface, SurfaceFormat::B8G8R8A8); NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map); } else { dataSurface = surface->GetDataSurface(); NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map); } NS_ENSURE_TRUE(dataSurface && mappedOK, NS_ERROR_FAILURE); MOZ_ASSERT(dataSurface->GetFormat() == SurfaceFormat::B8G8R8A8); uint8_t* data = nullptr; UniquePtr<uint8_t[]> autoDeleteArray; if (map.mStride == BytesPerPixel(dataSurface->GetFormat()) * iconSize.width) { // Mapped data is already packed data = map.mData; } else { // We can't use map.mData since the pixels are not packed (as required by // CreateDIBitmap, which is called under the DataToBitmap call below). // // We must unmap before calling SurfaceToPackedBGRA because it needs access // to the pixel data. dataSurface->Unmap(); map.mData = nullptr; autoDeleteArray = SurfaceToPackedBGRA(dataSurface); data = autoDeleteArray.get(); NS_ENSURE_TRUE(data, NS_ERROR_FAILURE); } HBITMAP bmp = DataToBitmap(data, iconSize.width, -iconSize.height, 32); uint8_t* a1data = Data32BitTo1Bit(data, iconSize.width, iconSize.height); if (map.mData) { dataSurface->Unmap(); } if (!a1data) { return NS_ERROR_FAILURE; } HBITMAP mbmp = DataToBitmap(a1data, iconSize.width, -iconSize.height, 1); PR_Free(a1data); ICONINFO info = {0}; info.fIcon = !aIsCursor; info.xHotspot = aHotspotX; info.yHotspot = aHotspotY; info.hbmMask = mbmp; info.hbmColor = bmp; HCURSOR icon = ::CreateIconIndirect(&info); ::DeleteObject(mbmp); ::DeleteObject(bmp); if (!icon) return NS_ERROR_FAILURE; *aIcon = icon; return NS_OK; }
nsresult XRE_InitChildProcess(int aArgc, char* aArgv[], const XREChildData* aChildData) { NS_ENSURE_ARG_MIN(aArgc, 2); NS_ENSURE_ARG_POINTER(aArgv); NS_ENSURE_ARG_POINTER(aArgv[0]); MOZ_ASSERT(aChildData); #if defined(XP_LINUX) && defined(MOZ_SANDBOX) // This has to happen while we're still single-threaded. mozilla::SandboxEarlyInit(XRE_GetProcessType()); #endif #ifdef MOZ_JPROF // Call the code to install our handler setupProfilingStuff(); #endif #ifdef XP_LINUX // On Fennec, the GMPLoader's code resides inside XUL (because for the time // being GMPLoader relies upon NSPR, which we can't use in plugin-container // on Android), so we create it here inside XUL and pass it to the GMP code. // // On desktop Linux, the sandbox code lives in a shared library, and // the GMPLoader is in libxul instead of executables to avoid unwanted // library dependencies. mozilla::gmp::SandboxStarter* starter = nullptr; #ifdef MOZ_GMP_SANDBOX starter = LinuxSandboxStarter::Make(); #endif UniquePtr<GMPLoader> loader = CreateGMPLoader(starter); GMPProcessChild::SetGMPLoader(loader.get()); #else // On non-Linux platforms, the GMPLoader code resides in plugin-container, // and we must forward it through to the GMP code here. GMPProcessChild::SetGMPLoader(aChildData->gmpLoader.get()); #endif #if defined(XP_WIN) // From the --attach-console support in nsNativeAppSupportWin.cpp, but // here we are a content child process, so we always attempt to attach // to the parent's (ie, the browser's) console. // Try to attach console to the parent process. // It will succeed when the parent process is a command line, // so that stdio will be displayed in it. if (AttachConsole(ATTACH_PARENT_PROCESS)) { // Change std handles to refer to new console handles. // Before doing so, ensure that stdout/stderr haven't been // redirected to a valid file if (_fileno(stdout) == -1 || _get_osfhandle(fileno(stdout)) == -1) freopen("CONOUT$", "w", stdout); // Merge stderr into CONOUT$ since there isn't any `CONERR$`. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx if (_fileno(stderr) == -1 || _get_osfhandle(fileno(stderr)) == -1) freopen("CONOUT$", "w", stderr); if (_fileno(stdin) == -1 || _get_osfhandle(fileno(stdin)) == -1) freopen("CONIN$", "r", stdin); } #if defined(MOZ_SANDBOX) if (aChildData->sandboxTargetServices) { SandboxTarget::Instance()->SetTargetServices(aChildData->sandboxTargetServices); } #endif #endif // NB: This must be called before profiler_init ScopedLogging logger; // This is needed by Telemetry to initialize histogram collection. // NB: This must be called after NS_LogInit(). // NS_LogInit must be called before Telemetry::CreateStatisticsRecorder // so as to avoid many log messages of the form // WARNING: XPCOM objects created/destroyed from static ctor/dtor: [..] // See bug 1279614. Telemetry::CreateStatisticsRecorder(); mozilla::LogModule::Init(); char aLocal; GeckoProfilerInitRAII profiler(&aLocal); PROFILER_LABEL("Startup", "XRE_InitChildProcess", js::ProfileEntry::Category::OTHER); // Complete 'task_t' exchange for Mac OS X. This structure has the same size // regardless of architecture so we don't have any cross-arch issues here. #ifdef XP_MACOSX if (aArgc < 1) return NS_ERROR_FAILURE; const char* const mach_port_name = aArgv[--aArgc]; const int kTimeoutMs = 1000; MachSendMessage child_message(0); if (!child_message.AddDescriptor(MachMsgPortDescriptor(mach_task_self()))) { NS_WARNING("child AddDescriptor(mach_task_self()) failed."); return NS_ERROR_FAILURE; } ReceivePort child_recv_port; mach_port_t raw_child_recv_port = child_recv_port.GetPort(); if (!child_message.AddDescriptor(MachMsgPortDescriptor(raw_child_recv_port))) { NS_WARNING("Adding descriptor to message failed"); return NS_ERROR_FAILURE; } ReceivePort* ports_out_receiver = new ReceivePort(); if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_out_receiver->GetPort()))) { NS_WARNING("Adding descriptor to message failed"); return NS_ERROR_FAILURE; } ReceivePort* ports_in_receiver = new ReceivePort(); if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_in_receiver->GetPort()))) { NS_WARNING("Adding descriptor to message failed"); return NS_ERROR_FAILURE; } MachPortSender child_sender(mach_port_name); kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs); if (err != KERN_SUCCESS) { NS_WARNING("child SendMessage() failed"); return NS_ERROR_FAILURE; } MachReceiveMessage parent_message; err = child_recv_port.WaitForMessage(&parent_message, kTimeoutMs); if (err != KERN_SUCCESS) { NS_WARNING("child WaitForMessage() failed"); return NS_ERROR_FAILURE; } if (parent_message.GetTranslatedPort(0) == MACH_PORT_NULL) { NS_WARNING("child GetTranslatedPort(0) failed"); return NS_ERROR_FAILURE; } err = task_set_bootstrap_port(mach_task_self(), parent_message.GetTranslatedPort(0)); if (parent_message.GetTranslatedPort(1) == MACH_PORT_NULL) { NS_WARNING("child GetTranslatedPort(1) failed"); return NS_ERROR_FAILURE; } MachPortSender* ports_out_sender = new MachPortSender(parent_message.GetTranslatedPort(1)); if (parent_message.GetTranslatedPort(2) == MACH_PORT_NULL) { NS_WARNING("child GetTranslatedPort(2) failed"); return NS_ERROR_FAILURE; } MachPortSender* ports_in_sender = new MachPortSender(parent_message.GetTranslatedPort(2)); if (err != KERN_SUCCESS) { NS_WARNING("child task_set_bootstrap_port() failed"); return NS_ERROR_FAILURE; } #endif SetupErrorHandling(aArgv[0]); #if defined(MOZ_CRASHREPORTER) if (aArgc < 1) return NS_ERROR_FAILURE; const char* const crashReporterArg = aArgv[--aArgc]; # if defined(XP_WIN) || defined(XP_MACOSX) // on windows and mac, |crashReporterArg| is the named pipe on which the // server is listening for requests, or "-" if crash reporting is // disabled. if (0 != strcmp("-", crashReporterArg) && !XRE_SetRemoteExceptionHandler(crashReporterArg)) { // Bug 684322 will add better visibility into this condition NS_WARNING("Could not setup crash reporting\n"); } # elif defined(OS_LINUX) // on POSIX, |crashReporterArg| is "true" if crash reporting is // enabled, false otherwise if (0 != strcmp("false", crashReporterArg) && !XRE_SetRemoteExceptionHandler(nullptr)) { // Bug 684322 will add better visibility into this condition NS_WARNING("Could not setup crash reporting\n"); } # else # error "OOP crash reporting unsupported on this platform" # endif #endif // if defined(MOZ_CRASHREPORTER) gArgv = aArgv; gArgc = aArgc; #ifdef MOZ_X11 XInitThreads(); #endif #if MOZ_WIDGET_GTK == 2 XRE_GlibInit(); #endif #ifdef MOZ_WIDGET_GTK // Setting the name here avoids the need to pass this through to gtk_init(). g_set_prgname(aArgv[0]); #endif #ifdef OS_POSIX if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") || PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) { printf_stderr("\n\nCHILDCHILDCHILDCHILD\n debug me @ %d\n\n", base::GetCurrentProcId()); sleep(30); } #elif defined(OS_WIN) if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS")) { NS_DebugBreak(NS_DEBUG_BREAK, "Invoking NS_DebugBreak() to debug child process", nullptr, __FILE__, __LINE__); } else if (PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) { printf_stderr("\n\nCHILDCHILDCHILDCHILD\n debug me @ %d\n\n", base::GetCurrentProcId()); ::Sleep(10000); } #endif // child processes launched by GeckoChildProcessHost get this magic // argument appended to their command lines const char* const parentPIDString = aArgv[aArgc-1]; MOZ_ASSERT(parentPIDString, "NULL parent PID"); --aArgc; char* end = 0; base::ProcessId parentPID = strtol(parentPIDString, &end, 10); MOZ_ASSERT(!*end, "invalid parent PID"); #ifdef XP_MACOSX mozilla::ipc::SharedMemoryBasic::SetupMachMemory(parentPID, ports_in_receiver, ports_in_sender, ports_out_sender, ports_out_receiver, true); #endif #if defined(XP_WIN) // On Win7+, register the application user model id passed in by // parent. This insures windows created by the container properly // group with the parent app on the Win7 taskbar. const char* const appModelUserId = aArgv[--aArgc]; if (appModelUserId) { // '-' implies no support if (*appModelUserId != '-') { nsString appId; appId.AssignWithConversion(nsDependentCString(appModelUserId)); // The version string is encased in quotes appId.Trim(NS_LITERAL_CSTRING("\"").get()); // Set the id SetTaskbarGroupId(appId); } } #endif base::AtExitManager exitManager; nsresult rv = XRE_InitCommandLine(aArgc, aArgv); if (NS_FAILED(rv)) { return NS_ERROR_FAILURE; } MessageLoop::Type uiLoopType; switch (XRE_GetProcessType()) { case GeckoProcessType_Content: case GeckoProcessType_GPU: // Content processes need the XPCOM/chromium frankenventloop uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD; break; case GeckoProcessType_GMPlugin: uiLoopType = MessageLoop::TYPE_DEFAULT; break; default: uiLoopType = MessageLoop::TYPE_UI; break; } { // This is a lexical scope for the MessageLoop below. We want it // to go out of scope before NS_LogTerm() so that we don't get // spurious warnings about XPCOM objects being destroyed from a // static context. // Associate this thread with a UI MessageLoop MessageLoop uiMessageLoop(uiLoopType); { nsAutoPtr<ProcessChild> process; #ifdef XP_WIN mozilla::ipc::windows::InitUIThread(); #endif switch (XRE_GetProcessType()) { case GeckoProcessType_Default: MOZ_CRASH("This makes no sense"); break; case GeckoProcessType_Plugin: process = new PluginProcessChild(parentPID); break; case GeckoProcessType_Content: { process = new ContentProcess(parentPID); // If passed in grab the application path for xpcom init bool foundAppdir = false; #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) // If passed in grab the profile path for sandboxing bool foundProfile = false; #endif for (int idx = aArgc; idx > 0; idx--) { if (aArgv[idx] && !strcmp(aArgv[idx], "-appdir")) { MOZ_ASSERT(!foundAppdir); if (foundAppdir) { continue; } nsCString appDir; appDir.Assign(nsDependentCString(aArgv[idx+1])); static_cast<ContentProcess*>(process.get())->SetAppDir(appDir); foundAppdir = true; } #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) if (aArgv[idx] && !strcmp(aArgv[idx], "-profile")) { MOZ_ASSERT(!foundProfile); if (foundProfile) { continue; } nsCString profile; profile.Assign(nsDependentCString(aArgv[idx+1])); static_cast<ContentProcess*>(process.get())->SetProfile(profile); foundProfile = true; } if (foundProfile && foundAppdir) { break; } #else if (foundAppdir) { break; } #endif /* XP_MACOSX && MOZ_CONTENT_SANDBOX */ } } break; case GeckoProcessType_IPDLUnitTest: #ifdef MOZ_IPDL_TESTS process = new IPDLUnitTestProcessChild(parentPID); #else MOZ_CRASH("rebuild with --enable-ipdl-tests"); #endif break; case GeckoProcessType_GMPlugin: process = new gmp::GMPProcessChild(parentPID); break; case GeckoProcessType_GPU: process = new gfx::GPUProcessImpl(parentPID); break; default: MOZ_CRASH("Unknown main thread class"); } if (!process->Init()) { return NS_ERROR_FAILURE; } #ifdef MOZ_CRASHREPORTER #if defined(XP_WIN) || defined(XP_MACOSX) CrashReporter::InitChildProcessTmpDir(); #endif #endif #if defined(XP_WIN) // Set child processes up such that they will get killed after the // chrome process is killed in cases where the user shuts the system // down or logs off. ::SetProcessShutdownParameters(0x280 - 1, SHUTDOWN_NORETRY); #endif #if defined(MOZ_SANDBOX) && defined(XP_WIN) // We need to do this after the process has been initialised, as // InitLoggingIfRequired may need access to prefs. mozilla::sandboxing::InitLoggingIfRequired(aChildData->ProvideLogFunction); #endif OverrideDefaultLocaleIfNeeded(); #if defined(MOZ_CRASHREPORTER) #if defined(MOZ_CONTENT_SANDBOX) && !defined(MOZ_WIDGET_GONK) AddContentSandboxLevelAnnotation(); #endif #endif // Run the UI event loop on the main thread. uiMessageLoop.MessageLoop::Run(); // Allow ProcessChild to clean up after itself before going out of // scope and being deleted process->CleanUp(); mozilla::Omnijar::CleanUp(); #if defined(XP_MACOSX) // Everybody should be done using shared memory by now. mozilla::ipc::SharedMemoryBasic::Shutdown(); #endif } } Telemetry::DestroyStatisticsRecorder(); return XRE_DeinitCommandLine(); }
bool GMPLoaderImpl::Load(const char* aUTF8LibPath, uint32_t aUTF8LibPathLen, char* aOriginSalt, uint32_t aOriginSaltLen, const GMPPlatformAPI* aPlatformAPI, GMPAdapter* aAdapter) { std::string nodeId; if (!CalculateGMPDeviceId(aOriginSalt, aOriginSaltLen, nodeId)) { return false; } // Start the sandbox now that we've generated the device bound node id. // This must happen after the node id is bound to the device id, as // generating the device id requires privileges. if (mSandboxStarter && !mSandboxStarter->Start(aUTF8LibPath)) { return false; } // Load the GMP. PRLibSpec libSpec; #ifdef XP_WIN int pathLen = MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, nullptr, 0); if (pathLen == 0) { return false; } auto widePath = MakeUnique<wchar_t[]>(pathLen); if (MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, widePath.get(), pathLen) == 0) { return false; } libSpec.value.pathname_u = widePath.get(); libSpec.type = PR_LibSpec_PathnameU; #else libSpec.value.pathname = aUTF8LibPath; libSpec.type = PR_LibSpec_Pathname; #endif PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, 0); if (!lib) { return false; } GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(lib, "GMPInit")); if ((initFunc && aAdapter) || (!initFunc && !aAdapter)) { // Ensure that if we're dealing with a GMP we do *not* use an adapter // provided from the outside world. This is important as it means we // don't call code not covered by Adobe's plugin-container voucher // before we pass the node Id to Adobe's GMP. return false; } // Note: PassThroughGMPAdapter's code must remain in this file so that it's // covered by Adobe's plugin-container voucher. mAdapter.reset((!aAdapter) ? new PassThroughGMPAdapter() : aAdapter); mAdapter->SetAdaptee(lib); if (mAdapter->GMPInit(aPlatformAPI) != GMPNoErr) { return false; } mAdapter->GMPSetNodeId(nodeId.c_str(), nodeId.size()); return true; }
// We now define the matrix assembly function for the // Laplace system. We need to first compute element // matrices and right-hand sides, and then take into // account the boundary conditions, which will be handled // via a penalty method. void assemble_laplace(EquationSystems& es, const std::string& system_name) { #ifdef LIBMESH_ENABLE_AMR // It is a good idea to make sure we are assembling // the proper system. libmesh_assert_equal_to (system_name, "Laplace"); // Declare a performance log. Give it a descriptive // string to identify what part of the code we are // logging, since there may be many PerfLogs in an // application. PerfLog perf_log ("Matrix Assembly",false); // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are running const unsigned int mesh_dim = mesh.mesh_dimension(); // Get a reference to the LinearImplicitSystem we are solving LinearImplicitSystem& system = es.get_system<LinearImplicitSystem>("Laplace"); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = system.get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p UniquePtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. UniquePtr<FEBase> fe (FEBase::build(mesh_dim, fe_type)); UniquePtr<FEBase> fe_face (FEBase::build(mesh_dim, fe_type)); // Quadrature rules for numerical integration. UniquePtr<QBase> qrule(fe_type.default_quadrature_rule(mesh_dim)); UniquePtr<QBase> qface(fe_type.default_quadrature_rule(mesh_dim-1)); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (qrule.get()); fe_face->attach_quadrature_rule (qface.get()); // Here we define some references to cell-specific data that // will be used to assemble the linear system. // We begin with the element Jacobian * quadrature weight at each // integration point. const std::vector<Real>& JxW = fe->get_JxW(); const std::vector<Real>& JxW_face = fe_face->get_JxW(); // The physical XY locations of the quadrature points on the element. // These might be useful for evaluating spatially varying material // properties or forcing functions at the quadrature points. const std::vector<Point>& q_point = fe->get_xyz(); // The element shape functions evaluated at the quadrature points. // For this simple problem we usually only need them on element // boundaries. const std::vector<std::vector<Real> >& phi = fe->get_phi(); const std::vector<std::vector<Real> >& psi = fe_face->get_phi(); // The element shape function gradients evaluated at the quadrature // points. const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // The XY locations of the quadrature points used for face integration const std::vector<Point>& qface_points = fe_face->get_xyz(); // Define data structures to contain the element matrix // and right-hand-side vector contribution. Following // basic finite element terminology we will denote these // "Ke" and "Fe". More detail is in example 3. DenseMatrix<Number> Ke; DenseVector<Number> Fe; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices; // Now we will loop over all the elements in the mesh. We will // compute the element matrix and right-hand-side contribution. See // example 3 for a discussion of the element iterators. Here we use // the \p const_active_local_elem_iterator to indicate we only want // to loop over elements that are assigned to the local processor // which are "active" in the sense of AMR. This allows each // processor to compute its components of the global matrix for // active elements while ignoring parent elements which have been // refined. MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Start logging the shape function initialization. // This is done through a simple function call with // the name of the event to log. perf_log.push("elem init"); // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe->reinit (elem); // Zero the element matrix and right-hand side before // summing them. We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Ke.resize (dof_indices.size(), dof_indices.size()); Fe.resize (dof_indices.size()); // Stop logging the shape function initialization. // If you forget to stop logging an event the PerfLog // object will probably catch the error and abort. perf_log.pop("elem init"); // Now we will build the element matrix. This involves // a double loop to integrate the test funcions (i) against // the trial functions (j). // // Now start logging the element matrix computation perf_log.push ("Ke"); for (unsigned int qp=0; qp<qrule->n_points(); qp++) for (unsigned int i=0; i<dphi.size(); i++) for (unsigned int j=0; j<dphi.size(); j++) Ke(i,j) += JxW[qp]*(dphi[i][qp]*dphi[j][qp]); // We need a forcing function to make the 1D case interesting if (mesh_dim == 1) for (unsigned int qp=0; qp<qrule->n_points(); qp++) { Real x = q_point[qp](0); Real f = singularity ? sqrt(3.)/9.*pow(-x, -4./3.) : cos(x); for (unsigned int i=0; i<dphi.size(); ++i) Fe(i) += JxW[qp]*phi[i][qp]*f; } // Stop logging the matrix computation perf_log.pop ("Ke"); // At this point the interior element integration has // been completed. However, we have not yet addressed // boundary conditions. For this example we will only // consider simple Dirichlet boundary conditions imposed // via the penalty method. // // This approach adds the L2 projection of the boundary // data in penalty form to the weak statement. This is // a more generic approach for applying Dirichlet BCs // which is applicable to non-Lagrange finite element // discretizations. { // Start logging the boundary condition computation perf_log.push ("BCs"); // The penalty value. const Real penalty = 1.e10; // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. for (unsigned int s=0; s<elem->n_sides(); s++) if (elem->neighbor(s) == NULL) { fe_face->reinit(elem,s); for (unsigned int qp=0; qp<qface->n_points(); qp++) { const Number value = exact_solution (qface_points[qp], es.parameters, "null", "void"); // RHS contribution for (unsigned int i=0; i<psi.size(); i++) Fe(i) += penalty*JxW_face[qp]*value*psi[i][qp]; // Matrix contribution for (unsigned int i=0; i<psi.size(); i++) for (unsigned int j=0; j<psi.size(); j++) Ke(i,j) += penalty*JxW_face[qp]*psi[i][qp]*psi[j][qp]; } } // Stop logging the boundary condition computation perf_log.pop ("BCs"); } // The element matrix and right-hand-side are now built // for this element. Add them to the global matrix and // right-hand-side vector. The \p SparseMatrix::add_matrix() // and \p NumericVector::add_vector() members do this for us. // Start logging the insertion of the local (element) // matrix and vector into the global matrix and vector perf_log.push ("matrix insertion"); dof_map.constrain_element_matrix_and_vector(Ke, Fe, dof_indices); system.matrix->add_matrix (Ke, dof_indices); system.rhs->add_vector (Fe, dof_indices); // Start logging the insertion of the local (element) // matrix and vector into the global matrix and vector perf_log.pop ("matrix insertion"); } // That's it. We don't need to do anything else to the // PerfLog. When it goes out of scope (at this function return) // it will print its log to the screen. Pretty easy, huh? #endif // #ifdef LIBMESH_ENABLE_AMR }
static bool WeakMap_construct(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // ES6 draft rev 31 (15 Jan 2015) 23.3.1.1 step 1. if (!ThrowIfNotConstructing(cx, args, "WeakMap")) return false; RootedObject obj(cx, NewBuiltinClassInstance(cx, &WeakMapObject::class_)); if (!obj) return false; // Steps 5-6, 11. if (!args.get(0).isNullOrUndefined()) { // Steps 7a-b. RootedValue adderVal(cx); if (!GetProperty(cx, obj, obj, cx->names().set, &adderVal)) return false; // Step 7c. if (!IsCallable(adderVal)) return ReportIsNotFunction(cx, adderVal); bool isOriginalAdder = IsNativeFunction(adderVal, WeakMap_set); RootedValue mapVal(cx, ObjectValue(*obj)); FastInvokeGuard fig(cx, adderVal); InvokeArgs& args2 = fig.args(); // Steps 7d-e. JS::ForOfIterator iter(cx); if (!iter.init(args[0])) return false; RootedValue pairVal(cx); RootedObject pairObject(cx); RootedValue keyVal(cx); RootedObject keyObject(cx); RootedValue val(cx); while (true) { // Steps 12a-e. bool done; if (!iter.next(&pairVal, &done)) return false; if (done) break; // Step 12f. if (!pairVal.isObject()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INVALID_MAP_ITERABLE, "WeakMap"); return false; } pairObject = &pairVal.toObject(); if (!pairObject) return false; // Steps 12g-h. if (!GetElement(cx, pairObject, pairObject, 0, &keyVal)) return false; // Steps 12i-j. if (!GetElement(cx, pairObject, pairObject, 1, &val)) return false; // Steps 12k-l. if (isOriginalAdder) { if (keyVal.isPrimitive()) { UniquePtr<char[], JS::FreePolicy> bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, nullptr); if (!bytes) return false; JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes.get()); return false; } keyObject = &keyVal.toObject(); if (!SetWeakMapEntry(cx, obj, keyObject, val)) return false; } else { if (!args2.init(2)) return false; args2.setCallee(adderVal); args2.setThis(mapVal); args2[0].set(keyVal); args2[1].set(val); if (!fig.invoke(cx)) return false; } } } args.rval().setObject(*obj); return true; }
/* * Experimental implementation of ArrayBuffer.transfer: * https://gist.github.com/andhow/95fb9e49996615764eff * which is currently in the early stages of proposal for ES7. */ bool ArrayBufferObject::fun_transfer(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); HandleValue oldBufferArg = args.get(0); HandleValue newByteLengthArg = args.get(1); if (!oldBufferArg.isObject()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } RootedObject oldBufferObj(cx, &oldBufferArg.toObject()); if (!ObjectClassIs(oldBufferObj, ESClass_ArrayBuffer, cx)) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } // Beware: oldBuffer can point across compartment boundaries. ArrayBuffer // contents are not compartment-specific so this is safe. Rooted<ArrayBufferObject*> oldBuffer(cx); if (oldBufferObj->is<ArrayBufferObject>()) { oldBuffer = &oldBufferObj->as<ArrayBufferObject>(); } else { JSObject* unwrapped = CheckedUnwrap(oldBufferObj); if (!unwrapped || !unwrapped->is<ArrayBufferObject>()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } oldBuffer = &unwrapped->as<ArrayBufferObject>(); } size_t oldByteLength = oldBuffer->byteLength(); size_t newByteLength; if (newByteLengthArg.isUndefined()) { newByteLength = oldByteLength; } else { int32_t i32; if (!ToInt32(cx, newByteLengthArg, &i32)) return false; if (i32 < 0) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); return false; } newByteLength = size_t(i32); } if (oldBuffer->isNeutered()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED); return false; } UniquePtr<uint8_t, JS::FreePolicy> newData; if (!newByteLength) { if (!ArrayBufferObject::neuter(cx, oldBuffer, oldBuffer->contents())) return false; } else { # if defined(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB) // With a 4gb mapped asm.js buffer, we can simply enable/disable access // to the delta as long as the requested length is page-sized. if (oldBuffer->isAsmJSMapped() && (newByteLength % AsmJSPageSize) == 0) return TransferAsmJSMappedBuffer(cx, args, oldBuffer, newByteLength); # endif // Since we try to realloc below, only allow stealing malloc'd buffers. // If !hasMallocedContents, stealContents will malloc a copy which we // can then realloc. bool steal = oldBuffer->hasMallocedContents(); auto stolenContents = ArrayBufferObject::stealContents(cx, oldBuffer, steal); if (!stolenContents) return false; UniquePtr<uint8_t, JS::FreePolicy> oldData(stolenContents.data()); if (newByteLength > oldByteLength) { // In theory, realloc+memset(0) can be optimized to avoid touching // any pages (by using OS page mapping tricks). However, in // practice, we don't seem to get this optimization in Firefox with // jemalloc so calloc+memcpy are faster. newData.reset(cx->runtime()->pod_callocCanGC<uint8_t>(newByteLength)); if (newData) { memcpy(newData.get(), oldData.get(), oldByteLength); } else { // Try malloc before giving up since it might be able to succed // by resizing oldData in-place. newData.reset(cx->pod_realloc(oldData.get(), oldByteLength, newByteLength)); if (!newData) return false; oldData.release(); memset(newData.get() + oldByteLength, 0, newByteLength - oldByteLength); } } else if (newByteLength < oldByteLength) { newData.reset(cx->pod_realloc(oldData.get(), oldByteLength, newByteLength)); if (!newData) return false; oldData.release(); } else { newData = Move(oldData); } } RootedObject newBuffer(cx, JS_NewArrayBufferWithContents(cx, newByteLength, newData.get())); if (!newBuffer) return false; newData.release(); args.rval().setObject(*newBuffer); return true; }
Mappable * MappableExtractFile::Create(const char *name, Zip *zip, Zip::Stream *stream) { MOZ_ASSERT(zip && stream); const char *cachePath = getenv("MOZ_LINKER_CACHE"); if (!cachePath || !*cachePath) { WARN("MOZ_LINKER_EXTRACT is set, but not MOZ_LINKER_CACHE; " "not extracting"); return nullptr; } UniquePtr<char[]> path = MakeUnique<char[]>(strlen(cachePath) + strlen(name) + 2); sprintf(path.get(), "%s/%s", cachePath, name); CacheValidator validator(path.get(), zip, stream); if (validator.IsValid()) { DEBUG_LOG("Reusing %s", static_cast<char *>(path.get())); return MappableFile::Create(path.get()); } DEBUG_LOG("Extracting to %s", static_cast<char *>(path.get())); AutoCloseFD fd; fd = open(path.get(), O_TRUNC | O_RDWR | O_CREAT | O_NOATIME, S_IRUSR | S_IWUSR); if (fd == -1) { ERROR("Couldn't open %s to decompress library", path.get()); return nullptr; } AutoUnlinkFile file(path.release()); if (stream->GetType() == Zip::Stream::DEFLATE) { if (ftruncate(fd, stream->GetUncompressedSize()) == -1) { ERROR("Couldn't ftruncate %s to decompress library", file.get()); return nullptr; } /* Map the temporary file for use as inflate buffer */ MappedPtr buffer(MemoryRange::mmap(nullptr, stream->GetUncompressedSize(), PROT_WRITE, MAP_SHARED, fd, 0)); if (buffer == MAP_FAILED) { ERROR("Couldn't map %s to decompress library", file.get()); return nullptr; } zxx_stream zStream = stream->GetZStream(buffer); /* Decompress */ if (inflateInit2(&zStream, -MAX_WBITS) != Z_OK) { ERROR("inflateInit failed: %s", zStream.msg); return nullptr; } if (inflate(&zStream, Z_FINISH) != Z_STREAM_END) { ERROR("inflate failed: %s", zStream.msg); return nullptr; } if (inflateEnd(&zStream) != Z_OK) { ERROR("inflateEnd failed: %s", zStream.msg); return nullptr; } if (zStream.total_out != stream->GetUncompressedSize()) { ERROR("File not fully uncompressed! %ld / %d", zStream.total_out, static_cast<unsigned int>(stream->GetUncompressedSize())); return nullptr; } } else if (stream->GetType() == Zip::Stream::STORE) { SeekableZStream zStream; if (!zStream.Init(stream->GetBuffer(), stream->GetSize())) { ERROR("Couldn't initialize SeekableZStream for %s", name); return nullptr; } if (ftruncate(fd, zStream.GetUncompressedSize()) == -1) { ERROR("Couldn't ftruncate %s to decompress library", file.get()); return nullptr; } MappedPtr buffer(MemoryRange::mmap(nullptr, zStream.GetUncompressedSize(), PROT_WRITE, MAP_SHARED, fd, 0)); if (buffer == MAP_FAILED) { ERROR("Couldn't map %s to decompress library", file.get()); return nullptr; } if (!zStream.Decompress(buffer, 0, zStream.GetUncompressedSize())) { ERROR("%s: failed to decompress", name); return nullptr; } } else { return nullptr; } validator.CacheChecksum(); return new MappableExtractFile(fd.forget(), file.release()); }
/** * Starts the upgrade process for update of the service if it is * already installed. * * @param installDir the installation directory where * maintenanceservice_installer.exe is located. * @return TRUE if successful */ BOOL StartServiceUpdate(LPCWSTR installDir) { // Get a handle to the local computer SCM database SC_HANDLE manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); if (!manager) { return FALSE; } // Open the service SC_HANDLE svc = OpenServiceW(manager, SVC_NAME, SERVICE_ALL_ACCESS); if (!svc) { CloseServiceHandle(manager); return FALSE; } // If we reach here, then the service is installed, so // proceed with upgrading it. CloseServiceHandle(manager); // The service exists and we opened it, get the config bytes needed DWORD bytesNeeded; if (!QueryServiceConfigW(svc, nullptr, 0, &bytesNeeded) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { CloseServiceHandle(svc); return FALSE; } // Get the service config information, in particular we want the binary // path of the service. UniquePtr<char[]> serviceConfigBuffer = MakeUnique<char[]>(bytesNeeded); if (!QueryServiceConfigW(svc, reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()), bytesNeeded, &bytesNeeded)) { CloseServiceHandle(svc); return FALSE; } CloseServiceHandle(svc); QUERY_SERVICE_CONFIGW &serviceConfig = *reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()); PathUnquoteSpacesW(serviceConfig.lpBinaryPathName); // Obtain the temp path of the maintenance service binary WCHAR tmpService[MAX_PATH + 1] = { L'\0' }; if (!PathGetSiblingFilePath(tmpService, serviceConfig.lpBinaryPathName, L"maintenanceservice_tmp.exe")) { return FALSE; } // Get the new maintenance service path from the install dir WCHAR newMaintServicePath[MAX_PATH + 1] = { L'\0' }; wcsncpy(newMaintServicePath, installDir, MAX_PATH); PathAppendSafe(newMaintServicePath, L"maintenanceservice.exe"); // Copy the temp file in alongside the maintenace service. // This is a requirement for maintenance service upgrades. if (!CopyFileW(newMaintServicePath, tmpService, FALSE)) { return FALSE; } // Start the upgrade comparison process STARTUPINFOW si = {0}; si.cb = sizeof(STARTUPINFOW); // No particular desktop because no UI si.lpDesktop = L""; PROCESS_INFORMATION pi = {0}; WCHAR cmdLine[64] = { '\0' }; wcsncpy(cmdLine, L"dummyparam.exe upgrade", sizeof(cmdLine) / sizeof(cmdLine[0]) - 1); BOOL svcUpdateProcessStarted = CreateProcessW(tmpService, cmdLine, nullptr, nullptr, FALSE, 0, nullptr, installDir, &si, &pi); if (svcUpdateProcessStarted) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } return svcUpdateProcessStarted; }
/*static*/ void SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest, SurfaceFactory* factory) { GLContext* gl = src->mGL; // If `src` begins locked, it must end locked, though we may // temporarily unlock it if we need to. MOZ_ASSERT((src == gl->GetLockedSurface()) == src->IsLocked()); gl->MakeCurrent(); if (src->mAttachType == AttachmentType::Screen && dest->mAttachType == AttachmentType::Screen) { // Here, we actually need to blit through a temp surface, so let's make one. UniquePtr<SharedSurface_GLTexture> tempSurf; tempSurf = SharedSurface_GLTexture::Create(gl, gl, factory->mFormats, src->mSize, factory->mCaps.alpha); ProdCopy(src, tempSurf.get(), factory); ProdCopy(tempSurf.get(), dest, factory); return; } if (src->mAttachType == AttachmentType::Screen) { SharedSurface* origLocked = gl->GetLockedSurface(); bool srcNeedsUnlock = false; bool origNeedsRelock = false; if (origLocked != src) { if (origLocked) { origLocked->UnlockProd(); origNeedsRelock = true; } src->LockProd(); srcNeedsUnlock = true; } if (dest->mAttachType == AttachmentType::GLTexture) { GLuint destTex = dest->ProdTexture(); GLenum destTarget = dest->ProdTextureTarget(); gl->BlitHelper()->BlitFramebufferToTexture(0, destTex, src->mSize, dest->mSize, destTarget, true); } else if (dest->mAttachType == AttachmentType::GLRenderbuffer) { GLuint destRB = dest->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); gl->BlitHelper()->BlitFramebufferToFramebuffer(0, destWrapper.FB(), src->mSize, dest->mSize, true); } else { MOZ_CRASH("Unhandled dest->mAttachType."); } if (srcNeedsUnlock) src->UnlockProd(); if (origNeedsRelock) origLocked->LockProd(); return; } if (dest->mAttachType == AttachmentType::Screen) { SharedSurface* origLocked = gl->GetLockedSurface(); bool destNeedsUnlock = false; bool origNeedsRelock = false; if (origLocked != dest) { if (origLocked) { origLocked->UnlockProd(); origNeedsRelock = true; } dest->LockProd(); destNeedsUnlock = true; } if (src->mAttachType == AttachmentType::GLTexture) { GLuint srcTex = src->ProdTexture(); GLenum srcTarget = src->ProdTextureTarget(); gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0, src->mSize, dest->mSize, srcTarget, true); } else if (src->mAttachType == AttachmentType::GLRenderbuffer) { GLuint srcRB = src->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB); gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), 0, src->mSize, dest->mSize, true); } else { MOZ_CRASH("Unhandled src->mAttachType."); } if (destNeedsUnlock) dest->UnlockProd(); if (origNeedsRelock) origLocked->LockProd(); return; } // Alright, done with cases involving Screen types. // Only {src,dest}x{texture,renderbuffer} left. if (src->mAttachType == AttachmentType::GLTexture) { GLuint srcTex = src->ProdTexture(); GLenum srcTarget = src->ProdTextureTarget(); if (dest->mAttachType == AttachmentType::GLTexture) { GLuint destTex = dest->ProdTexture(); GLenum destTarget = dest->ProdTextureTarget(); gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex, src->mSize, dest->mSize, srcTarget, destTarget); return; } if (dest->mAttachType == AttachmentType::GLRenderbuffer) { GLuint destRB = dest->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(), src->mSize, dest->mSize, srcTarget); return; } MOZ_CRASH("Unhandled dest->mAttachType."); } if (src->mAttachType == AttachmentType::GLRenderbuffer) { GLuint srcRB = src->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB); if (dest->mAttachType == AttachmentType::GLTexture) { GLuint destTex = dest->ProdTexture(); GLenum destTarget = dest->ProdTextureTarget(); gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex, src->mSize, dest->mSize, destTarget); return; } if (dest->mAttachType == AttachmentType::GLRenderbuffer) { GLuint destRB = dest->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), destWrapper.FB(), src->mSize, dest->mSize); return; } MOZ_CRASH("Unhandled dest->mAttachType."); } MOZ_CRASH("Unhandled src->mAttachType."); }
UniquePtr<TrackInfo> MP4TrackDemuxer::GetInfo() const { return mInfo->Clone(); }
NS_IMETHODIMP nsPNGEncoder::AddImageFrame(const uint8_t* aData, uint32_t aLength, // (unused, req'd by JS) uint32_t aWidth, uint32_t aHeight, uint32_t aStride, uint32_t aInputFormat, const nsAString& aFrameOptions) { bool useTransparency= true; uint32_t delay_ms = 500; #ifdef PNG_APNG_SUPPORTED uint32_t dispose_op = PNG_DISPOSE_OP_NONE; uint32_t blend_op = PNG_BLEND_OP_SOURCE; #else uint32_t dispose_op; uint32_t blend_op; #endif uint32_t x_offset = 0, y_offset = 0; // must be initialized if (mImageBuffer == nullptr) { return NS_ERROR_NOT_INITIALIZED; } // EndImageEncode was done, or some error occurred earlier if (!mPNG) { return NS_BASE_STREAM_CLOSED; } // validate input format if (aInputFormat != INPUT_FORMAT_RGB && aInputFormat != INPUT_FORMAT_RGBA && aInputFormat != INPUT_FORMAT_HOSTARGB) return NS_ERROR_INVALID_ARG; // libpng's error handler jumps back here upon an error. if (setjmp(png_jmpbuf(mPNG))) { png_destroy_write_struct(&mPNG, &mPNGinfo); return NS_ERROR_FAILURE; } // parse and check any provided output options nsresult rv = ParseOptions(aFrameOptions, &useTransparency, nullptr, nullptr, nullptr, &dispose_op, &blend_op, &delay_ms, &x_offset, &y_offset); if (rv != NS_OK) { return rv; } #ifdef PNG_APNG_SUPPORTED if (mIsAnimation) { // XXX the row pointers arg (#3) is unused, can it be removed? png_write_frame_head(mPNG, mPNGinfo, nullptr, aWidth, aHeight, x_offset, y_offset, delay_ms, 1000, dispose_op, blend_op); } #endif // Stride is the padded width of each row, so it better be longer // (I'm afraid people will not understand what stride means, so // check it well) if ((aInputFormat == INPUT_FORMAT_RGB && aStride < aWidth * 3) || ((aInputFormat == INPUT_FORMAT_RGBA || aInputFormat == INPUT_FORMAT_HOSTARGB) && aStride < aWidth * 4)) { NS_WARNING("Invalid stride for InitFromData/AddImageFrame"); return NS_ERROR_INVALID_ARG; } #ifdef PNG_WRITE_FILTER_SUPPORTED png_set_filter(mPNG, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE); #endif // write each row: if we add more input formats, we may want to // generalize the conversions if (aInputFormat == INPUT_FORMAT_HOSTARGB) { // PNG requires RGBA with post-multiplied alpha, so we need to // convert UniquePtr<uint8_t[]> row = MakeUnique<uint8_t[]>(aWidth * 4); for (uint32_t y = 0; y < aHeight; y++) { ConvertHostARGBRow(&aData[y * aStride], row.get(), aWidth, useTransparency); png_write_row(mPNG, row.get()); } } else if (aInputFormat == INPUT_FORMAT_RGBA && !useTransparency) { // RBGA, but we need to strip the alpha UniquePtr<uint8_t[]> row = MakeUnique<uint8_t[]>(aWidth * 4); for (uint32_t y = 0; y < aHeight; y++) { StripAlpha(&aData[y * aStride], row.get(), aWidth); png_write_row(mPNG, row.get()); } } else if (aInputFormat == INPUT_FORMAT_RGB || aInputFormat == INPUT_FORMAT_RGBA) { // simple RBG(A), no conversion needed for (uint32_t y = 0; y < aHeight; y++) { png_write_row(mPNG, (uint8_t*)&aData[y * aStride]); } } else { NS_NOTREACHED("Bad format type"); return NS_ERROR_INVALID_ARG; } #ifdef PNG_APNG_SUPPORTED if (mIsAnimation) { png_write_frame_tail(mPNG, mPNGinfo); } #endif return NS_OK; }
// Now we define the assemble function which will be used // by the EquationSystems object at each timestep to assemble // the linear system for solution. void assemble_cd (EquationSystems& es, const std::string& system_name) { #ifdef LIBMESH_ENABLE_AMR // It is a good idea to make sure we are assembling // the proper system. libmesh_assert_equal_to (system_name, "Convection-Diffusion"); // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); // Get a reference to the Convection-Diffusion system object. TransientLinearImplicitSystem & system = es.get_system<TransientLinearImplicitSystem> ("Convection-Diffusion"); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = system.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p UniquePtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); UniquePtr<FEBase> fe_face (FEBase::build(dim, fe_type)); // A Gauss quadrature rule for numerical integration. // Let the \p FEType object decide what order rule is appropriate. QGauss qrule (dim, fe_type.default_quadrature_order()); QGauss qface (dim-1, fe_type.default_quadrature_order()); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (&qrule); fe_face->attach_quadrature_rule (&qface); // Here we define some references to cell-specific data that // will be used to assemble the linear system. We will start // with the element Jacobian * quadrature weight at each integration point. const std::vector<Real>& JxW = fe->get_JxW(); const std::vector<Real>& JxW_face = fe_face->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> >& phi = fe->get_phi(); const std::vector<std::vector<Real> >& psi = fe_face->get_phi(); // The element shape function gradients evaluated at the quadrature // points. const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // The XY locations of the quadrature points used for face integration const std::vector<Point>& qface_points = fe_face->get_xyz(); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = system.get_dof_map(); // Define data structures to contain the element matrix // and right-hand-side vector contribution. Following // basic finite element terminology we will denote these // "Ke" and "Fe". DenseMatrix<Number> Ke; DenseVector<Number> Fe; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<dof_id_type> dof_indices; // Here we extract the velocity & parameters that we put in the // EquationSystems object. const RealVectorValue velocity = es.parameters.get<RealVectorValue> ("velocity"); const Real dt = es.parameters.get<Real> ("dt"); // Now we will loop over all the elements in the mesh that // live on the local processor. We will compute the element // matrix and right-hand-side contribution. Since the mesh // will be refined we want to only consider the ACTIVE elements, // hence we use a variant of the \p active_elem_iterator. MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe->reinit (elem); // Zero the element matrix and right-hand side before // summing them. We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Ke.resize (dof_indices.size(), dof_indices.size()); Fe.resize (dof_indices.size()); // Now we will build the element matrix and right-hand-side. // Constructing the RHS requires the solution and its // gradient from the previous timestep. This myst be // calculated at each quadrature point by summing the // solution degree-of-freedom values by the appropriate // weight functions. for (unsigned int qp=0; qp<qrule.n_points(); qp++) { // Values to hold the old solution & its gradient. Number u_old = 0.; Gradient grad_u_old; // Compute the old solution & its gradient. for (unsigned int l=0; l<phi.size(); l++) { u_old += phi[l][qp]*system.old_solution (dof_indices[l]); // This will work, // grad_u_old += dphi[l][qp]*system.old_solution (dof_indices[l]); // but we can do it without creating a temporary like this: grad_u_old.add_scaled (dphi[l][qp],system.old_solution (dof_indices[l])); } // Now compute the element matrix and RHS contributions. for (unsigned int i=0; i<phi.size(); i++) { // The RHS contribution Fe(i) += JxW[qp]*( // Mass matrix term u_old*phi[i][qp] + -.5*dt*( // Convection term // (grad_u_old may be complex, so the // order here is important!) (grad_u_old*velocity)*phi[i][qp] + // Diffusion term 0.01*(grad_u_old*dphi[i][qp])) ); for (unsigned int j=0; j<phi.size(); j++) { // The matrix contribution Ke(i,j) += JxW[qp]*( // Mass-matrix phi[i][qp]*phi[j][qp] + .5*dt*( // Convection term (velocity*dphi[j][qp])*phi[i][qp] + // Diffusion term 0.01*(dphi[i][qp]*dphi[j][qp])) ); } } } // At this point the interior element integration has // been completed. However, we have not yet addressed // boundary conditions. For this example we will only // consider simple Dirichlet boundary conditions imposed // via the penalty method. // // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. { // The penalty value. const Real penalty = 1.e10; // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. for (unsigned int s=0; s<elem->n_sides(); s++) if (elem->neighbor(s) == NULL) { fe_face->reinit(elem,s); for (unsigned int qp=0; qp<qface.n_points(); qp++) { const Number value = exact_solution (qface_points[qp](0), qface_points[qp](1), system.time); // RHS contribution for (unsigned int i=0; i<psi.size(); i++) Fe(i) += penalty*JxW_face[qp]*value*psi[i][qp]; // Matrix contribution for (unsigned int i=0; i<psi.size(); i++) for (unsigned int j=0; j<psi.size(); j++) Ke(i,j) += penalty*JxW_face[qp]*psi[i][qp]*psi[j][qp]; } } } // If this assembly program were to be used on an adaptive mesh, // we would have to apply any hanging node constraint equations dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); // The element matrix and right-hand-side are now built // for this element. Add them to the global matrix and // right-hand-side vector. The \p SparseMatrix::add_matrix() // and \p NumericVector::add_vector() members do this for us. system.matrix->add_matrix (Ke, dof_indices); system.rhs->add_vector (Fe, dof_indices); } // That concludes the system matrix assembly routine. #endif // #ifdef LIBMESH_ENABLE_AMR }
nsresult SdpHelper::AddCandidateToSdp(Sdp* sdp, const std::string& candidateUntrimmed, const std::string& mid, uint16_t level) { if (level >= sdp->GetMediaSectionCount()) { SDP_SET_ERROR("Index " << level << " out of range"); return NS_ERROR_INVALID_ARG; } // Trim off '[a=]candidate:' size_t begin = candidateUntrimmed.find(':'); if (begin == std::string::npos) { SDP_SET_ERROR("Invalid candidate, no ':' (" << candidateUntrimmed << ")"); return NS_ERROR_INVALID_ARG; } ++begin; std::string candidate = candidateUntrimmed.substr(begin); // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-11#section-3.4.2.1 // Implementations receiving an ICE Candidate object MUST use the MID if // present, or the m= line index, if not (as it could have come from a // non-JSEP endpoint). (bug 1095793) SdpMediaSection* msection = 0; if (!mid.empty()) { // FindMsectionByMid could return nullptr msection = FindMsectionByMid(*sdp, mid); // Check to make sure mid matches what we'd get by // looking up the m= line using the level. (mjf) std::string checkMid; nsresult rv = GetMidFromLevel(*sdp, level, &checkMid); if (NS_FAILED(rv)) { return rv; } if (mid != checkMid) { SDP_SET_ERROR("Mismatch between mid and level - \"" << mid << "\" is not the mid for level " << level << "; \"" << checkMid << "\" is"); return NS_ERROR_INVALID_ARG; } } if (!msection) { msection = &(sdp->GetMediaSection(level)); } SdpAttributeList& attrList = msection->GetAttributeList(); UniquePtr<SdpMultiStringAttribute> candidates; if (!attrList.HasAttribute(SdpAttribute::kCandidateAttribute)) { // Create new candidates.reset( new SdpMultiStringAttribute(SdpAttribute::kCandidateAttribute)); } else { // Copy existing candidates.reset(new SdpMultiStringAttribute( *static_cast<const SdpMultiStringAttribute*>( attrList.GetAttribute(SdpAttribute::kCandidateAttribute)))); } candidates->PushEntry(candidate); attrList.SetAttribute(candidates.release()); return NS_OK; }