void AbstractFeSurfaceIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::AssembleOnSurfaceElement( const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement, c_vector<double, PROBLEM_DIM*ELEMENT_DIM>& rBSurfElem) { c_vector<double, SPACE_DIM> weighted_direction; double jacobian_determinant; mpMesh->GetWeightedDirectionForBoundaryElement(rSurfaceElement.GetIndex(), weighted_direction, jacobian_determinant); rBSurfElem.clear(); // Allocate memory for the basis function values c_vector<double, ELEMENT_DIM> phi; // Loop over Gauss points for (unsigned quad_index=0; quad_index<mpSurfaceQuadRule->GetNumQuadPoints(); quad_index++) { const ChastePoint<ELEMENT_DIM-1>& quad_point = mpSurfaceQuadRule->rGetQuadPoint(quad_index); SurfaceBasisFunction::ComputeBasisFunctions(quad_point, phi); ////////////////////////////// // Interpolation: X only ////////////////////////////// // The location of the Gauss point in the original element will be stored in x ChastePoint<SPACE_DIM> x(0,0,0); this->ResetInterpolatedQuantities(); for (unsigned i=0; i<rSurfaceElement.GetNumNodes(); i++) { const c_vector<double, SPACE_DIM> node_loc = rSurfaceElement.GetNode(i)->rGetLocation(); x.rGetLocation() += phi(i)*node_loc; // Allow the concrete version of the assembler to interpolate any desired quantities this->IncrementInterpolatedQuantities(phi(i), rSurfaceElement.GetNode(i)); } ////////////////////////////////// // Create elemental contribution ////////////////////////////////// double wJ = jacobian_determinant * mpSurfaceQuadRule->GetWeight(quad_index); ///\todo #1321 Improve efficiency of Neumann BC implementation noalias(rBSurfElem) += ComputeVectorSurfaceTerm(rSurfaceElement, phi, x) * wJ; } }
void ContinuumMechanicsNeumannBcsAssembler<DIM>::AssembleOnBoundaryElement(BoundaryElement<DIM-1,DIM>& rBoundaryElement, c_vector<double,STENCIL_SIZE>& rBelem, unsigned boundaryConditionIndex) { rBelem.clear(); c_vector<double, DIM> weighted_direction; double jacobian_determinant; mpMesh->GetWeightedDirectionForBoundaryElement(rBoundaryElement.GetIndex(), weighted_direction, jacobian_determinant); c_vector<double,NUM_NODES_PER_ELEMENT> phi; for (unsigned quad_index=0; quad_index<mpQuadRule->GetNumQuadPoints(); quad_index++) { double wJ = jacobian_determinant * mpQuadRule->GetWeight(quad_index); const ChastePoint<DIM-1>& quad_point = mpQuadRule->rGetQuadPoint(quad_index); QuadraticBasisFunction<DIM-1>::ComputeBasisFunctions(quad_point, phi); c_vector<double,DIM> traction = zero_vector<double>(DIM); switch (mpProblemDefinition->GetTractionBoundaryConditionType()) { case ELEMENTWISE_TRACTION: { traction = mpProblemDefinition->rGetElementwiseTractions()[boundaryConditionIndex]; break; } default: // Functional traction not implemented yet.. NEVER_REACHED; } for (unsigned index=0; index<NUM_NODES_PER_ELEMENT*DIM; index++) { unsigned spatial_dim = index%DIM; unsigned node_index = (index-spatial_dim)/DIM; assert(node_index < NUM_NODES_PER_ELEMENT); rBelem(index) += traction(spatial_dim) * phi(node_index) * wJ; } } }