void AssemblyA0::interior_assembly(FEMContext & c) { const unsigned int n_components = rb_sys.n_vars(); // make sure we have three components libmesh_assert_equal_to (n_components, 3); const unsigned int u_var = rb_sys.u_var; const unsigned int v_var = rb_sys.v_var; const unsigned int w_var = rb_sys.w_var; FEBase * elem_fe = libmesh_nullptr; c.get_element_fe(u_var, elem_fe); const std::vector<Real> & JxW = elem_fe->get_JxW(); // The velocity shape function gradients at interior // quadrature points. const std::vector<std::vector<RealGradient>> & dphi = elem_fe->get_dphi(); // Now we will build the affine operator unsigned int n_qpoints = c.get_element_qrule().n_points(); std::vector<unsigned int> n_var_dofs(n_components); n_var_dofs[u_var] = c.get_dof_indices(u_var).size(); n_var_dofs[v_var] = c.get_dof_indices(v_var).size(); n_var_dofs[w_var] = c.get_dof_indices(w_var).size(); for (unsigned int C_i = 0; C_i < n_components; C_i++) { unsigned int C_j = 0; for (unsigned int C_k = 0; C_k < n_components; C_k++) for (unsigned int C_l = 1; C_l < n_components; C_l++) { Real C_ijkl = elasticity_tensor(C_i, C_j, C_k, C_l); for (unsigned int qp=0; qp<n_qpoints; qp++) for (unsigned int i=0; i<n_var_dofs[C_i]; i++) for (unsigned int j=0; j<n_var_dofs[C_k]; j++) (c.get_elem_jacobian(C_i,C_k))(i,j) += JxW[qp]*(C_ijkl * dphi[i][qp](C_j)*dphi[j][qp](C_l)); } } for (unsigned int C_i = 0; C_i < n_components; C_i++) for (unsigned int C_j = 1; C_j < n_components; C_j++) for (unsigned int C_k = 0; C_k < n_components; C_k++) { unsigned int C_l = 0; Real C_ijkl = elasticity_tensor(C_i, C_j, C_k, C_l); for (unsigned int qp=0; qp<n_qpoints; qp++) for (unsigned int i=0; i<n_var_dofs[C_i]; i++) for (unsigned int j=0; j<n_var_dofs[C_k]; j++) (c.get_elem_jacobian(C_i,C_k))(i,j) += JxW[qp]*(C_ijkl * dphi[i][qp](C_j)*dphi[j][qp](C_l)); } }
AutoPtr<DiffContext> FEMSystem::build_context () { FEMContext* fc = new FEMContext(*this); AutoPtr<DiffContext> ap(fc); DifferentiablePhysics* phys = this->get_physics(); libmesh_assert (phys); // If we are solving a moving mesh problem, tell that to the Context fc->set_mesh_system(phys->get_mesh_system()); fc->set_mesh_x_var(phys->get_mesh_x_var()); fc->set_mesh_y_var(phys->get_mesh_y_var()); fc->set_mesh_z_var(phys->get_mesh_z_var()); ap->set_deltat_pointer( &deltat ); // If we are solving the adjoint problem, tell that to the Context ap->is_adjoint() = this->get_time_solver().is_adjoint(); return ap; }
void InnerProductAssembly::interior_assembly(FEMContext & c) { const unsigned int u_var = rb_sys.u_var; const unsigned int v_var = rb_sys.v_var; const unsigned int w_var = rb_sys.w_var; FEBase * elem_fe = libmesh_nullptr; c.get_element_fe(u_var, elem_fe); const std::vector<Real> & JxW = elem_fe->get_JxW(); // The velocity shape function gradients at interior // quadrature points. const std::vector<std::vector<RealGradient> >& dphi = elem_fe->get_dphi(); // The number of local degrees of freedom in each variable const unsigned int n_u_dofs = c.get_dof_indices(u_var).size(); const unsigned int n_v_dofs = c.get_dof_indices(v_var).size(); const unsigned int n_w_dofs = c.get_dof_indices(w_var).size(); // Now we will build the affine operator unsigned int n_qpoints = c.get_element_qrule().n_points(); DenseSubMatrix<Number> & Kuu = c.get_elem_jacobian(u_var, u_var); DenseSubMatrix<Number> & Kvv = c.get_elem_jacobian(v_var, v_var); DenseSubMatrix<Number> & Kww = c.get_elem_jacobian(w_var, w_var); for (unsigned int qp=0; qp<n_qpoints; qp++) { 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]); 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]); for (unsigned int i=0; i<n_w_dofs; i++) for (unsigned int j=0; j<n_w_dofs; j++) Kww(i,j) += JxW[qp]*(dphi[i][qp]*dphi[j][qp]); } }
void FEMSystem::numerical_jacobian (TimeSolverResPtr res, FEMContext &context) { // Logging is done by numerical_elem_jacobian // or numerical_side_jacobian DenseVector<Number> original_residual(context.elem_residual); DenseVector<Number> backwards_residual(context.elem_residual); DenseMatrix<Number> numerical_jacobian(context.elem_jacobian); #ifdef DEBUG DenseMatrix<Number> old_jacobian(context.elem_jacobian); #endif Real numerical_point_h = 0.; if (_mesh_sys == this) numerical_point_h = numerical_jacobian_h * context.elem->hmin(); for (unsigned int j = 0; j != context.dof_indices.size(); ++j) { // Take the "minus" side of a central differenced first derivative Number original_solution = context.elem_solution(j); context.elem_solution(j) -= numerical_jacobian_h; // Make sure to catch any moving mesh terms // FIXME - this could be less ugly Real *coord = NULL; if (_mesh_sys == this) { if (_mesh_x_var != libMesh::invalid_uint) for (unsigned int k = 0; k != context.dof_indices_var[_mesh_x_var].size(); ++k) if (context.dof_indices_var[_mesh_x_var][k] == context.dof_indices[j]) coord = &(const_cast<Elem*>(context.elem)->point(k)(0)); if (_mesh_y_var != libMesh::invalid_uint) for (unsigned int k = 0; k != context.dof_indices_var[_mesh_y_var].size(); ++k) if (context.dof_indices_var[_mesh_y_var][k] == context.dof_indices[j]) coord = &(const_cast<Elem*>(context.elem)->point(k)(1)); if (_mesh_z_var != libMesh::invalid_uint) for (unsigned int k = 0; k != context.dof_indices_var[_mesh_z_var].size(); ++k) if (context.dof_indices_var[_mesh_z_var][k] == context.dof_indices[j]) coord = &(const_cast<Elem*>(context.elem)->point(k)(2)); } if (coord) { // We have enough information to scale the perturbations // here appropriately context.elem_solution(j) = original_solution - numerical_point_h; *coord = libmesh_real(context.elem_solution(j)); } context.elem_residual.zero(); ((*time_solver).*(res))(false, context); #ifdef DEBUG libmesh_assert_equal_to (old_jacobian, context.elem_jacobian); #endif backwards_residual = context.elem_residual; // Take the "plus" side of a central differenced first derivative context.elem_solution(j) = original_solution + numerical_jacobian_h; if (coord) { context.elem_solution(j) = original_solution + numerical_point_h; *coord = libmesh_real(context.elem_solution(j)); } context.elem_residual.zero(); ((*time_solver).*(res))(false, context); #ifdef DEBUG libmesh_assert_equal_to (old_jacobian, context.elem_jacobian); #endif context.elem_solution(j) = original_solution; if (coord) { *coord = libmesh_real(context.elem_solution(j)); for (unsigned int i = 0; i != context.dof_indices.size(); ++i) { numerical_jacobian(i,j) = (context.elem_residual(i) - backwards_residual(i)) / 2. / numerical_point_h; } } else { for (unsigned int i = 0; i != context.dof_indices.size(); ++i) { numerical_jacobian(i,j) = (context.elem_residual(i) - backwards_residual(i)) / 2. / numerical_jacobian_h; } } } context.elem_residual = original_residual; context.elem_jacobian = numerical_jacobian; }