void TestWithCoarseSlightlyOutsideFine() throw(Exception) { // Fine mesh is has h=0.1, on unit cube (so 6000 elements) TetrahedralMesh<3,3> fine_mesh; fine_mesh.ConstructRegularSlabMesh(0.1, 1.0,1.0,1.0); // Coarse mesh is slightly bigger than in previous test QuadraticMesh<3> coarse_mesh(1.0, 1.0, 1.0, 1.0); // xmax > 1.0 coarse_mesh.Scale(1.03, 1.0, 1.0); FineCoarseMeshPair<3> mesh_pair(fine_mesh,coarse_mesh); GaussianQuadratureRule<3> quad_rule(3); // Need to call SetUpBoxesOnFineMesh first TS_ASSERT_THROWS_CONTAINS(mesh_pair.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, true), "Call"); mesh_pair.SetUpBoxesOnFineMesh(0.3); TS_ASSERT_EQUALS(mesh_pair.mpFineMeshBoxCollection->GetNumBoxes(), 4*4*4u); mesh_pair.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, true); TS_ASSERT_EQUALS(mesh_pair.mNotInMesh.size(), 2u); // hardcoded TS_ASSERT_EQUALS(mesh_pair.mNotInMeshNearestElementWeights.size(), 2u); TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights().size(), 6*8u); for (unsigned i=0; i<mesh_pair.rGetElementsAndWeights().size(); i++) { TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].ElementNum, fine_mesh.GetNumElements()); // comment out this test as now some of the weights are negative/greater than one //for (unsigned j=0; j<4; j++) //{ // TS_ASSERT_LESS_THAN(-1e14, mesh_pair.rGetElementsAndWeights()[i].Weights(j)); // TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].Weights(j), 1.0+1e-14); //} } /* * For each quadrature point that was not found in the fine mesh, check * that its x-value is greater than one - this is the only way it could * be outside the fine mesh. */ QuadraturePointsGroup<3> quad_point_posns(coarse_mesh, quad_rule); for (unsigned i=0; i<mesh_pair.mNotInMesh.size(); i++) { double x = quad_point_posns.rGet(mesh_pair.mNotInMesh[i])(0); TS_ASSERT_LESS_THAN(1.0, x); } mesh_pair.PrintStatistics(); TS_ASSERT_EQUALS( Warnings::Instance()->GetNumWarnings(), 1u); Warnings::Instance()->QuietDestroy(); }
/* * Test when calling ComputeFineElementsAndWeightsForCoarseQuadPoints() * in non-safe mode, but using the default value of box width. It is * difficult to get the class to run incorrectly (ie fail without an * assertion failing) in non-safe mode (ie we can't just specify boxes * that are too small), so we just test we get the same results as in * safe mode. */ void TestNonSafeMode() throw(Exception) { // Fine mesh is has h=0.1, on unit cube (so 6000 elements) TetrahedralMesh<3,3> fine_mesh; fine_mesh.ConstructRegularSlabMesh(0.1, 1.0, 1.0, 1.0); QuadraticMesh<3> coarse_mesh(1.0, 1.0, 1.0, 1.0); // xmax > 1.0 coarse_mesh.Scale(1.03, 1.0, 1.0); FineCoarseMeshPair<3> mesh_pair(fine_mesh,coarse_mesh); GaussianQuadratureRule<3> quad_rule(3); // Call SetUpBoxesOnFineMesh() without providing a width mesh_pair.SetUpBoxesOnFineMesh(); /* * Whereas before 4 by 4 by 4 boxes were explicitly chosen, here it * has been determined that 6 by 6 by 6 are needed. */ TS_ASSERT_EQUALS(mesh_pair.mpFineMeshBoxCollection->GetNumBoxes(), 6*6*6u); mesh_pair.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, false /* non-safe mode*/); TS_ASSERT_EQUALS(mesh_pair.mNotInMesh.size(), 2u); // hardcoded TS_ASSERT_EQUALS(mesh_pair.mNotInMeshNearestElementWeights.size(), 2u); TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights().size(), 6*8u); for (unsigned i=0; i<mesh_pair.rGetElementsAndWeights().size(); i++) { TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].ElementNum, fine_mesh.GetNumElements()); } /* * For each quadrature point that was not found in the fine mesh, check * that its x-value is greater than one - this is the only way it could * be outside the fine mesh. */ QuadraturePointsGroup<3> quad_point_posns(coarse_mesh, quad_rule); for (unsigned i=0; i<mesh_pair.mNotInMesh.size(); i++) { double x = quad_point_posns.rGet(mesh_pair.mNotInMesh[i])(0); TS_ASSERT_LESS_THAN(1.0, x); } mesh_pair.PrintStatistics(); TS_ASSERT_EQUALS( Warnings::Instance()->GetNumWarnings(), 1u); Warnings::Instance()->QuietDestroy(); }
void TestLinearBasisFunction0d() { ChastePoint<0> zero; TS_ASSERT_DELTA(LinearBasisFunction<0>::ComputeBasisFunction(zero, 0), 1.0, 1e-12); c_vector<double, 1> basis_function_vector; LinearBasisFunction<0>::ComputeBasisFunctions(zero,basis_function_vector); TS_ASSERT_EQUALS(basis_function_vector.size(), 1u); TS_ASSERT_DELTA(basis_function_vector[0], 1.0, 1e-12); // Check link with 0d quad rule works ok GaussianQuadratureRule<0> quad_rule(0); const ChastePoint<0>& quad_point = quad_rule.rGetQuadPoint(0); c_vector<double, 1> basis_function_vector2; LinearBasisFunction<0>::ComputeBasisFunctions(quad_point,basis_function_vector2); TS_ASSERT_EQUALS(basis_function_vector.size(), 1u); TS_ASSERT_DELTA(basis_function_vector[0], 1.0, 1e-12); }
// Covers some bits that aren't covered in the tests above, void TestOtherCoverage() throw(Exception) { TetrahedralMesh<2,2> fine_mesh; fine_mesh.ConstructRegularSlabMesh(0.1, 1.0, 1.0); QuadraticMesh<2> coarse_mesh(1.0, 1.0, 1.0); /* * Rotate the mesh by 45 degrees, makes it possible (since boxes no * longer lined up with elements) for the containing element of a * quad point to be in a *local* box, ie not an element contained * in the box containing this point. */ c_matrix<double,2,2> rotation_mat; rotation_mat(0,0) = 1.0/sqrt(2.0); rotation_mat(1,0) = -1.0/sqrt(2.0); rotation_mat(0,1) = 1.0/sqrt(2.0); rotation_mat(1,1) = 1.0/sqrt(2.0); fine_mesh.Rotate(rotation_mat); coarse_mesh.Rotate(rotation_mat); GaussianQuadratureRule<2> quad_rule(3); FineCoarseMeshPair<2> mesh_pair(fine_mesh,coarse_mesh); mesh_pair.SetUpBoxesOnFineMesh(); mesh_pair.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, true); TS_ASSERT_EQUALS(mesh_pair.mNotInMesh.size(), 0u); /* * Repeat again with smaller boxes, covers the bit requiring the whole * mesh to be searched to find an element for a particular quad point. */ FineCoarseMeshPair<2> mesh_pair2(fine_mesh,coarse_mesh); mesh_pair2.SetUpBoxesOnFineMesh(0.01); mesh_pair2.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, true); TS_ASSERT_EQUALS(mesh_pair.mNotInMesh.size(), 0u); }
void TestWithCoarseContainedInFine() throw(Exception) { // Fine mesh is has h=0.1, on unit cube (so 6000 elements) TetrahedralMesh<3,3> fine_mesh; fine_mesh.ConstructRegularSlabMesh(0.1, 1.0, 1.0, 1.0); // Coarse mesh is has h=1 on unit cube (so 6 elements) QuadraticMesh<3> coarse_mesh(1.0, 1.0, 1.0, 1.0); FineCoarseMeshPair<3> mesh_pair(fine_mesh,coarse_mesh); mesh_pair.SetUpBoxesOnFineMesh(0.3); TS_ASSERT_EQUALS(mesh_pair.mpFineMeshBoxCollection->GetNumBoxes(), 4*4*4u); // For each node, find containing box. That box should contain any element that node is in. for (unsigned i=0; i<fine_mesh.GetNumNodes(); i++) { unsigned box_index = mesh_pair.mpFineMeshBoxCollection->CalculateContainingBox(fine_mesh.GetNode(i)); assert(fine_mesh.GetNode(i)->rGetContainingElementIndices().size() > 0); for (std::set<unsigned>::iterator iter = fine_mesh.GetNode(i)->rGetContainingElementIndices().begin(); iter != fine_mesh.GetNode(i)->rGetContainingElementIndices().end(); ++iter) { Element<3,3>* p_element = fine_mesh.GetElement(*iter); TS_ASSERT_DIFFERS( mesh_pair.mpFineMeshBoxCollection->rGetBox(box_index).rGetElementsContained().find(p_element), mesh_pair.mpFineMeshBoxCollection->rGetBox(box_index).rGetElementsContained().end() ) } } GaussianQuadratureRule<3> quad_rule(3); mesh_pair.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, true); // All coarse quadrature points should have been found in the fine mesh TS_ASSERT_EQUALS(mesh_pair.mNotInMesh.size(), 0u); TS_ASSERT_EQUALS(mesh_pair.mNotInMeshNearestElementWeights.size(), 0u); // Check the elements and weights have been set up correctly // 6 elements, 8 quad points TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights().size(), 6*8u); // Some hardcoded values, just to check element_nums not all zero TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights()[0].ElementNum, 3816u); TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights()[10].ElementNum, 217u); TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights()[20].ElementNum, 1094u); for (unsigned i=0; i<mesh_pair.rGetElementsAndWeights().size(); i++) { TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].ElementNum, fine_mesh.GetNumElements()); /* * As all the quadrature points should have been found in the fine mesh, * all the weights should be between 0 and 1. * Note weights = (1-psi_x-psi_y-psi_z, psi_x, psi_y, psi_z), where psi * is the position of the point in that element when transformed to the * canonical element. */ for (unsigned j=0; j<4; j++) { TS_ASSERT_LESS_THAN(-1e14, mesh_pair.rGetElementsAndWeights()[i].Weights(j)); TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].Weights(j), 1.0+1e-14); } } TS_ASSERT_EQUALS(mesh_pair.mStatisticsCounters[0], 6*8u); TS_ASSERT_EQUALS(mesh_pair.mStatisticsCounters[1], 0u); mesh_pair.PrintStatistics(); mesh_pair.DeleteFineBoxCollection(); TS_ASSERT(mesh_pair.mpFineMeshBoxCollection==NULL); }
double AbstractFunctionalCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::CalculateOnElement(Element<ELEMENT_DIM, SPACE_DIM>& rElement) { double result_on_element = 0; // Third order quadrature. Note that the functional may be non-polynomial (see documentation of class). GaussianQuadratureRule<ELEMENT_DIM> quad_rule(3); /// NOTE: This assumes that the Jacobian is constant on an element, ie /// no curvilinear bases were used for position double jacobian_determinant; c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian; c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian; rElement.CalculateInverseJacobian(jacobian, jacobian_determinant, inverse_jacobian); const unsigned num_nodes = rElement.GetNumNodes(); // Loop over Gauss points for (unsigned quad_index=0; quad_index < quad_rule.GetNumQuadPoints(); quad_index++) { const ChastePoint<ELEMENT_DIM>& quad_point = quad_rule.rGetQuadPoint(quad_index); c_vector<double, ELEMENT_DIM+1> phi; LinearBasisFunction<ELEMENT_DIM>::ComputeBasisFunctions(quad_point, phi); c_matrix<double, ELEMENT_DIM, ELEMENT_DIM+1> grad_phi; LinearBasisFunction<ELEMENT_DIM>::ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi); // Location of the Gauss point in the original element will be stored in x ChastePoint<SPACE_DIM> x(0,0,0); c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM); c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM); for (unsigned i=0; i<num_nodes; i++) { const c_vector<double, SPACE_DIM>& r_node_loc = rElement.GetNode(i)->rGetLocation(); // Interpolate x x.rGetLocation() += phi(i)*r_node_loc; // Interpolate u and grad u unsigned node_global_index = rElement.GetNodeGlobalIndex(i); for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++) { // NOTE - following assumes that, if say there are two unknowns u and v, they // are stored in the current solution vector as // [U1 V1 U2 V2 ... U_n V_n] unsigned index_into_vec = PROBLEM_DIM*node_global_index + index_of_unknown; double u_at_node = mSolutionReplicated[index_into_vec]; u(index_of_unknown) += phi(i)*u_at_node; for (unsigned j=0; j<SPACE_DIM; j++) { grad_u(index_of_unknown,j) += grad_phi(j,i)*u_at_node; } } } double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index); result_on_element += GetIntegrand(x, u, grad_u) * wJ; } return result_on_element; }