void AssembleOptimization::assemble_A_and_F() { A_matrix->zero(); F_vector->zero(); const MeshBase & mesh = _sys.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); const unsigned int u_var = _sys.variable_number ("u"); const DofMap & dof_map = _sys.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<Real> > & phi = fe->get_phi(); const std::vector<std::vector<RealGradient> > & dphi = fe->get_dphi(); std::vector<dof_id_type> dof_indices; DenseMatrix<Number> Ke; DenseVector<Number> Fe; 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); const unsigned int n_dofs = dof_indices.size(); fe->reinit (elem); Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { for (unsigned int dof_i=0; dof_i<n_dofs; dof_i++) { for (unsigned int dof_j=0; dof_j<n_dofs; dof_j++) { Ke(dof_i, dof_j) += JxW[qp] * (dphi[dof_j][qp]* dphi[dof_i][qp]); } Fe(dof_i) += JxW[qp] * phi[dof_i][qp]; } } A_matrix->add_matrix (Ke, dof_indices); F_vector->add_vector (Fe, dof_indices); } A_matrix->close(); F_vector->close(); }
void Assembly::addJacobianBlock(SparseMatrix<Number> & jacobian, unsigned int ivar, unsigned int jvar, const DofMap & dof_map, std::vector<dof_id_type> & dof_indices) { DenseMatrix<Number> & ke = jacobianBlock(ivar, jvar); // stick it into the matrix std::vector<dof_id_type> di(dof_indices); dof_map.constrain_element_matrix(ke, di, false); Real scaling_factor = _sys.getVariable(_tid, ivar).scalingFactor(); if (scaling_factor != 1.0) { _tmp_Ke = ke; _tmp_Ke *= scaling_factor; jacobian.add_matrix(_tmp_Ke, di); } else jacobian.add_matrix(ke, di); }
void Assembly::addJacobianBlock(SparseMatrix<Number> & jacobian, DenseMatrix<Number> & jac_block, const std::vector<dof_id_type> & idof_indices, const std::vector<dof_id_type> & jdof_indices, Real scaling_factor) { if ((idof_indices.size() > 0) && (jdof_indices.size() > 0) && jac_block.n() && jac_block.m()) { std::vector<dof_id_type> di(idof_indices); std::vector<dof_id_type> dj(jdof_indices); _dof_map.constrain_element_matrix(jac_block, di, dj, false); if (scaling_factor != 1.0) { _tmp_Ke = jac_block; _tmp_Ke *= scaling_factor; jacobian.add_matrix(_tmp_Ke, di, dj); } else jacobian.add_matrix(jac_block, di, dj); } }
void Assembly::addJacobianNeighbor(SparseMatrix<Number> & jacobian, unsigned int ivar, unsigned int jvar, const DofMap & dof_map, std::vector<dof_id_type> & dof_indices, std::vector<dof_id_type> & neighbor_dof_indices) { DenseMatrix<Number> & kee = jacobianBlock(ivar, jvar); DenseMatrix<Number> & ken = jacobianBlockNeighbor(Moose::ElementNeighbor, ivar, jvar); DenseMatrix<Number> & kne = jacobianBlockNeighbor(Moose::NeighborElement, ivar, jvar); DenseMatrix<Number> & knn = jacobianBlockNeighbor(Moose::NeighborNeighbor, ivar, jvar); std::vector<dof_id_type> di(dof_indices); std::vector<dof_id_type> dn(neighbor_dof_indices); // stick it into the matrix dof_map.constrain_element_matrix(kee, di, false); dof_map.constrain_element_matrix(ken, di, dn, false); dof_map.constrain_element_matrix(kne, dn, di, false); dof_map.constrain_element_matrix(knn, dn, false); Real scaling_factor = _sys.getVariable(_tid, ivar).scalingFactor(); if (scaling_factor != 1.0) { _tmp_Ke = ken; _tmp_Ke *= scaling_factor; jacobian.add_matrix(_tmp_Ke, di, dn); _tmp_Ke = kne; _tmp_Ke *= scaling_factor; jacobian.add_matrix(_tmp_Ke, dn, di); _tmp_Ke = knn; _tmp_Ke *= scaling_factor; jacobian.add_matrix(_tmp_Ke, dn); } else { jacobian.add_matrix(ken, di, dn); jacobian.add_matrix(kne, dn, di); jacobian.add_matrix(knn, dn); } }
// This function computes the Jacobian K(x) void compute_jacobian (const NumericVector<Number>& soln, SparseMatrix<Number>& jacobian, NonlinearImplicitSystem& sys) { // Get a reference to the equation system. EquationSystems &es = *_equation_system; // 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 AutoPtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. AutoPtr<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<unsigned int> 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 K = 1./std::sqrt(1. + grad_u*grad_u); 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]) + 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. }
void AssembleOptimization::assemble_A_and_F() { A_matrix->zero(); F_vector->zero(); const MeshBase & mesh = _sys.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); const unsigned int u_var = _sys.variable_number ("u"); const DofMap & dof_map = _sys.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<Real> > & phi = fe->get_phi(); const std::vector<std::vector<RealGradient> > & dphi = fe->get_dphi(); std::vector<dof_id_type> dof_indices; DenseMatrix<Number> Ke; DenseVector<Number> Fe; 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); const unsigned int n_dofs = dof_indices.size(); fe->reinit (elem); Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { for (unsigned int dof_i=0; dof_i<n_dofs; dof_i++) { for (unsigned int dof_j=0; dof_j<n_dofs; dof_j++) { Ke(dof_i, dof_j) += JxW[qp] * (dphi[dof_j][qp]* dphi[dof_i][qp]); } Fe(dof_i) += JxW[qp] * phi[dof_i][qp]; } } // This will zero off-diagonal entries of Ke corresponding to // Dirichlet dofs. dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); // We want the diagonal of constrained dofs to be zero too for (unsigned int local_dof_index=0; local_dof_index<n_dofs; local_dof_index++) { dof_id_type global_dof_index = dof_indices[local_dof_index]; if (dof_map.is_constrained_dof(global_dof_index)) { Ke(local_dof_index, local_dof_index) = 0.; } } A_matrix->add_matrix (Ke, dof_indices); F_vector->add_vector (Fe, dof_indices); } A_matrix->close(); F_vector->close(); }
/** * Evaluate the Jacobian of the nonlinear system. */ virtual void jacobian (const NumericVector<Number> & soln, SparseMatrix<Number> & jacobian, NonlinearImplicitSystem & /*sys*/) { const Real young_modulus = es.parameters.get<Real>("young_modulus"); const Real poisson_ratio = es.parameters.get<Real>("poisson_ratio"); const MeshBase & mesh = es.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); NonlinearImplicitSystem & system = es.get_system<NonlinearImplicitSystem>("NonlinearElasticity"); 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); std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type)); QGauss qrule (dim, fe_type.default_quadrature_order()); fe->attach_quadrature_rule (&qrule); std::unique_ptr<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)} }; std::vector<dof_id_type> dof_indices; std::vector<std::vector<dof_id_type>> dof_indices_var(3); jacobian.zero(); for (const auto & elem : mesh.active_local_element_ptr_range()) { 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); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { DenseVector<Number> u_vec(3); DenseMatrix<Number> grad_u(3, 3); for (unsigned int var_i=0; var_i<3; var_i++) { for (unsigned int j=0; j<n_var_dofs; j++) u_vec(var_i) += phi[j][qp]*soln(dof_indices_var[var_i][j]); // Row is variable u1, u2, or u3, column is x, y, or z for (unsigned int var_j=0; var_j<3; var_j++) for (unsigned int j=0; j<n_var_dofs; j++) grad_u(var_i,var_j) += dphi[j][qp](var_j)*soln(dof_indices_var[var_i][j]); } DenseMatrix<Number> strain_tensor(3, 3); for (unsigned int i=0; i<3; i++) for (unsigned int j=0; j<3; j++) { strain_tensor(i,j) += 0.5 * (grad_u(i,j) + grad_u(j,i)); for (unsigned int k=0; k<3; k++) strain_tensor(i,j) += 0.5 * grad_u(k,i)*grad_u(k,j); } // Define the deformation gradient DenseMatrix<Number> F(3, 3); F = grad_u; for (unsigned int var=0; var<3; var++) F(var, var) += 1.; 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(young_modulus, poisson_ratio, i, j, k, l) * strain_tensor(k, l); 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 m=0; m<3; m++) Ke_var[i][i](dof_i,dof_j) += JxW[qp] * (-dphi[dof_j][qp](m) * stress_tensor(m,j) * dphi[dof_i][qp](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++) { Number FxC_ijkl = 0.; for (unsigned int m=0; m<3; m++) FxC_ijkl += F(i,m) * elasticity_tensor(young_modulus, poisson_ratio, m, j, k, l); Ke_var[i][k](dof_i,dof_j) += JxW[qp] * (-0.5 * FxC_ijkl * dphi[dof_j][qp](l) * dphi[dof_i][qp](j)); Ke_var[i][l](dof_i,dof_j) += JxW[qp] * (-0.5 * FxC_ijkl * dphi[dof_j][qp](k) * dphi[dof_i][qp](j)); for (unsigned int n=0; n<3; n++) Ke_var[i][n](dof_i,dof_j) += JxW[qp] * (-0.5 * FxC_ijkl * (dphi[dof_j][qp](k) * grad_u(n,l) + dphi[dof_j][qp](l) * grad_u(n,k)) * dphi[dof_i][qp](j)); } } } dof_map.constrain_element_matrix (Ke, dof_indices); jacobian.add_matrix (Ke, dof_indices); } }