From 76b3455791a5165b0b4443ce4989d6be27849bcc Mon Sep 17 00:00:00 2001 From: Martin Kronbichler Date: Wed, 31 May 2017 12:39:07 +0200 Subject: [PATCH] Simplify initial guess for Newton iteration of transform_real_to_unit_cell --- source/fe/mapping_q_generic.cc | 233 +++++---------------------------- 1 file changed, 35 insertions(+), 198 deletions(-) diff --git a/source/fe/mapping_q_generic.cc b/source/fe/mapping_q_generic.cc index 557d0a045d..aea160c369 100644 --- a/source/fe/mapping_q_generic.cc +++ b/source/fe/mapping_q_generic.cc @@ -188,160 +188,6 @@ namespace internal - /** - * Compute an initial guess to pass to the Newton method in - * transform_real_to_unit_cell. For the initial guess we proceed in the - * following way: - * - * - * @note if dim - struct TransformR2UInitialGuess - { - static const double KA[GeometryInfo::vertices_per_cell][dim]; - static const double Kb[GeometryInfo::vertices_per_cell]; - }; - - - /* - Octave code: - M=[0 1; 1 1]; - K1 = transpose(M) * inverse (M*transpose(M)); - printf ("{%f, %f},\n", K1' ); - */ - template <> - const double - TransformR2UInitialGuess<1>:: - KA[GeometryInfo<1>::vertices_per_cell][1] = - { - {-1.000000}, - {1.000000} - }; - - template <> - const double - TransformR2UInitialGuess<1>:: - Kb[GeometryInfo<1>::vertices_per_cell] = {1.000000, 0.000000}; - - - /* - Octave code: - M=[0 1 0 1;0 0 1 1;1 1 1 1]; - K2 = transpose(M) * inverse (M*transpose(M)); - printf ("{%f, %f, %f},\n", K2' ); - */ - template <> - const double - TransformR2UInitialGuess<2>:: - KA[GeometryInfo<2>::vertices_per_cell][2] = - { - {-0.500000, -0.500000}, - { 0.500000, -0.500000}, - {-0.500000, 0.500000}, - { 0.500000, 0.500000} - }; - - /* - Octave code: - M=[0 1 0 1 0 1 0 1;0 0 1 1 0 0 1 1; 0 0 0 0 1 1 1 1; 1 1 1 1 1 1 1 1]; - K3 = transpose(M) * inverse (M*transpose(M)) - printf ("{%f, %f, %f, %f},\n", K3' ); - */ - template <> - const double - TransformR2UInitialGuess<2>:: - Kb[GeometryInfo<2>::vertices_per_cell] = - {0.750000,0.250000,0.250000,-0.250000 }; - - - template <> - const double - TransformR2UInitialGuess<3>:: - KA[GeometryInfo<3>::vertices_per_cell][3] = - { - {-0.250000, -0.250000, -0.250000}, - { 0.250000, -0.250000, -0.250000}, - {-0.250000, 0.250000, -0.250000}, - { 0.250000, 0.250000, -0.250000}, - {-0.250000, -0.250000, 0.250000}, - { 0.250000, -0.250000, 0.250000}, - {-0.250000, 0.250000, 0.250000}, - { 0.250000, 0.250000, 0.250000} - - }; - - - template <> - const double - TransformR2UInitialGuess<3>:: - Kb[GeometryInfo<3>::vertices_per_cell] = - {0.500000,0.250000,0.250000,0.000000,0.250000,0.000000,0.000000,-0.250000}; - - template - Point - transform_real_to_unit_cell_initial_guess (const std::vector > &vertex, - const Point &p) - { - Point p_unit; - - dealii::FullMatrix KA(GeometryInfo::vertices_per_cell, dim); - dealii::Vector Kb(GeometryInfo::vertices_per_cell); - - KA.fill( (double *)(TransformR2UInitialGuess::KA) ); - for (unsigned int i=0; i::vertices_per_cell; ++i) - Kb(i) = TransformR2UInitialGuess::Kb[i]; - - FullMatrix Y(spacedim, GeometryInfo::vertices_per_cell); - for (unsigned int v=0; v::vertices_per_cell; v++) - for (unsigned int i=0; i A(spacedim,dim); - Y.mmult(A,KA); // A = Y*KA - dealii::Vector b(spacedim); - Y.vmult(b,Kb); // b = Y*Kb - - for (unsigned int i=0; i dest(dim); - - FullMatrix A_1(dim,spacedim); - if (dim void compute_shape_function_values_general (const unsigned int n_shape_functions, const std::vector > &unit_points, @@ -1865,11 +1711,7 @@ transform_real_to_unit_cell (const typename Triangulation::cell_it if (spacedim == 1) return internal::MappingQ1::transform_real_to_unit_cell(vertices, p); else - { - const std::vector > a (vertices.begin(), - vertices.end()); - return internal::MappingQ1::transform_real_to_unit_cell_initial_guess(a,p); - } + break; } case 2: @@ -1908,54 +1750,49 @@ transform_real_to_unit_cell (const typename Triangulation::cell_it } + // Find the initial value for the Newton iteration by a normal + // projection to the least square plane determined by the vertices + // of the cell Point initial_p_unit; - if (polynomial_degree == 1) + if (this->preserves_vertex_locations()) + initial_p_unit = cell->real_to_unit_cell_affine_approximation(p); + else { - // Find the initial value for the Newton iteration by a normal - // projection to the least square plane determined by the vertices - // of the cell - const std::vector > a + // for the MappingQEulerian type classes, we want to still call the cell + // iterator's affine approximation. do so by creating a dummy + // triangulation with just the first vertices. + // + // we do this by first getting all support points, then + // throwing away all but the vertices, and finally calling + // the same function as above + std::vector > a = this->compute_mapping_support_points (cell); - Assert(a.size() == GeometryInfo::vertices_per_cell, - ExcInternalError()); - initial_p_unit = internal::MappingQ1::transform_real_to_unit_cell_initial_guess(a,p); + a.resize(GeometryInfo::vertices_per_cell); + std::vector > cells(1); + for (unsigned int i=0; i::vertices_per_cell; ++i) + cells[0].vertices[i] = i; + Triangulation tria; + tria.create_triangulation(a, cells, SubCellData()); + initial_p_unit = tria.begin_active()->real_to_unit_cell_affine_approximation(p); + } + // in 1d with spacedim > 1 the affine approximation is exact + if (dim == 1 && polynomial_degree == 1) + { + return initial_p_unit; } else { - try - { - // Find the initial value for the Newton iteration by a normal - // projection to the least square plane determined by the vertices - // of the cell - // - // we do this by first getting all support points, then - // throwing away all but the vertices, and finally calling - // the same function as above - std::vector > a - = this->compute_mapping_support_points (cell); - a.resize(GeometryInfo::vertices_per_cell); - initial_p_unit = internal::MappingQ1::transform_real_to_unit_cell_initial_guess(a,p); - } - catch (const typename Mapping::ExcTransformationFailed &) - { - for (unsigned int d=0; d::project_to_unit_cell(initial_p_unit); - } - // perform the Newton iteration and return the result. note that - // this statement may throw an exception, which we simply pass up to - // the caller - return this->transform_real_to_unit_cell_internal(cell, p, initial_p_unit); + // perform the Newton iteration and return the result. note that this + // statement may throw an exception, which we simply pass up to the + // caller + return this->transform_real_to_unit_cell_internal(cell, p, initial_p_unit); + } } -- 2.39.5