Hi Wolfgang and Jörg I am taking advantage for a second question. I have made a few minor changes in the code and re-implemented it. In serial version, all works fine so far. However, when running in parallel, I am seeing an issue in the method PlasticityContactProblem::update_solution_and_constraints.
In particular, it turns out that the value of const unsigned int index_z = dof_indices[q_point]; might be out of the range of TrilinosWrappers::MPI::Vector <http://www.dealii.org/8.5.0/doxygen/deal.II/classTrilinosWrappers_1_1MPI_1_1Vector.html> lambda(locally_relevant_dofs, mpi_communicator); lambda = newton_rhs_uncondensed; I have solved run-time issues by checking if if ( lambda.in_local_range(index_z)) but I wonder if the issue is possible (in principle, I mean) for the published code or is it my implementation that is not correct? Note that I am basically implementing step-42 upon the code built in step-20 using PETScWrappers::MPI::Vector, rather than step-40. If of use, I am writing my method below. Thanks for your help. Alberto ::update_solution_and_constraints () // The following function is the first function we call in each outer loop of the Newton iteration. // What it does is to project the solution onto the feasible set and update the active set for the degrees of freedom that touch or penetrate the obstacle. { std::pair <unsigned, unsigned> vrange; this->IO.log() << " In update_solution_and_constraints. " << std::flush; // We need to write into the solution vector (which we can only do with fully distributed vectors without ghost elements) and we need to read the Lagrange multiplier and the elements of the diagonal mass matrix from their respective vectors (which we can only do with vectors that do have ghost elements), so we create the respective vectors. We then also initialize the constraints object that will contain constraints from contact, as well as an object that contains an index set of all locally owned degrees of freedom that are part of the contact: std::vector<bool> dof_touched( this->dof_handler.n_dofs(), false); PETScWrappers::MPI::Vector distributed_solution( this->locally_owned_dofs, this->mpi_communicator ); distributed_solution = this->accumulated_displacement; vrange = distributed_solution.local_range(); this->IO.log() << " distributed_solution local range = " << vrange.first << ", " << vrange.second << "\n" << std::flush; PETScWrappers::MPI::Vector lambda( this->locally_relevant_dofs, this ->mpi_communicator); lambda = this->system_rhs_uncondensed; vrange = lambda.local_range(); this->IO.log() << " lambda local range = " << vrange.first << ", " << vrange.second << "\n" << std::flush; PETScWrappers::MPI::Vector diag_mass_matrix_vector_relevant( this->locally_relevant_dofs, this->mpi_communicator); diag_mass_matrix_vector_relevant = this->diag_mass_matrix_vector; vrange = diag_mass_matrix_vector_relevant.local_range(); this->IO.log() << " diag_mass_matrix_vector_relevant local range = " << vrange.first << ", " << vrange.second << "\n" << std::flush; this->all_constraints.reinit( this->locally_relevant_dofs ); this->contact_constraints.reinit( this->locally_relevant_dofs ); this->active_set.clear(); // The second part is a loop over all cells in which we look at each point where a degree of freedom is defined whether the active set condition is true and we need to add this degree of freedom to the active set of contact nodes. As we always do, if we want to evaluate functions at individual points, we do this with an FEValues object (or, here, an FEFaceValues object since we need to check contact at the surface) with an appropriately chosen quadrature object. We create this face quadrature object by choosing the "support points" of the shape functions defined on the faces of cells (for more on support points, see this glossary entry). As a consequence, we have as many quadrature points as there are shape functions per face and looping over quadrature points is equivalent to looping over shape functions defined on a face. With this, the code looks as follows: Quadrature<dim-1> face_quadrature( this ->fe.get_unit_face_support_points()); FEFaceValues<dim> fe_values_face( this->fe, face_quadrature, update_quadrature_points ); const unsigned int dofs_per_face = this->fe.dofs_per_face; const unsigned int n_face_q_points = face_quadrature.size(); std::vector<types::global_dof_index> dof_indices(dofs_per_face); typename DoFHandler<dim>::active_cell_iterator cell = this->dof_handler.begin_active(), endc = this->dof_handler.end(); for (; cell != endc; ++cell) if (!cell->is_artificial()) { if (cell->is_locally_owned()) // MY OWN CODE { for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face) // the Contact boundary is set to value 3, i.e. set_boundary_id (3); if (cell->face(face)->at_boundary() && cell->face(face)->boundary_id() == 3) { fe_values_face.reinit(cell, face); cell->face(face)->get_dof_indices(dof_indices); for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point) { // At each quadrature point (i.e., at each support point of a degree of freedom located on the contact boundary), we then ask whether it is part of the X2-displacement degrees of freedom and if we haven't encountered this degree of freedom yet (which can happen for those on the edges between faces), we need to evaluate the gap between the deformed object and the obstacle. If the active set condition is true, then we add a constraint to the ConstraintMatrix object that the next Newton update needs to satisfy, set the solution vector's corresponding element to the correct value, and add the index to the IndexSet object that stores which degree of freedom is part of the contact: const unsigned int component = this ->fe.face_system_to_component_index(q_point).first; const unsigned int index_X2 = dof_indices[q_point]; // MY OWN CODE: component has been changed to 1 since the direction of contact is X2 for the cell. if ((component == 1) && (dof_touched[index_X2] == false)) { dof_touched[index_X2] = true; const Point<dim> this_support_point = fe_values_face.quadrature_point(q_point); const double obstacle_value = this->obstacle->value(this_support_point, 1); const double solution_here = this->accumulated_displacement(index_X2); // solution(index_X2); // I believe it should be undeformed_gap >=0, i.e. : const double undeformed_gap = this_support_point(1) - obstacle_value; // rather than obstacle_value - this_support_point(1); double e_modulus; if ( cell->material_id() == 0 ) e_modulus = this ->cytoplasm_model.youngmodulus(); else if ( cell->material_id() == 1 ) e_modulus = this ->nucleus_model.youngmodulus(); else e_modulus = 1; if ( lambda.in_local_range(index_X2) && diag_mass_matrix_vector_relevant.in_local_range(index_X2) ) { lambda(index_X2); diag_mass_matrix_vector_relevant(index_X2); this->hanging_node_constraints.is_constrained(index_X2); const double c = 100.0 * e_modulus; if ((lambda(index_X2) / diag_mass_matrix_vector_relevant(index_X2) + c * ( - solution_here - undeformed_gap ) // I believe it should be this, rather than (solution_here - undeformed_gap) > 0) && !(this->hanging_node_constraints.is_constrained(index_X2)) ) { this->contact_constraints.add_line( index_X2 ); // it was this->all_constraints.add_line(index_X2); this->contact_constraints.set_inhomogeneity(index_X2, - undeformed_gap); // it was this->all_constraints.set_inhomogeneity // I believe it should be this, rather than undeformed_gap); distributed_solution( index_X2 ) = - undeformed_gap; // I believe it should be this, rather than undeformed_gap; this->active_set.add_index( index_X2 ); } }; } } } } } // At the end of this function, we exchange data between processors updating those ghost elements in the solution variable that have been written by other processors. distributed_solution.compress(VectorOperation::insert); this->accumulated_displacement = distributed_solution; // We then merge the constraints from hanging nodes into the ConstraintMatrix object that already contains the active set. this->contact_constraints.close(); // it was this->all_constraints.close(); this->all_constraints.merge(this->hanging_node_constraints); this->all_constraints.merge(this->contact_constraints); this->pcout << " Size of active set: " << Utilities::MPI::sum((this->active_set & this->locally_owned_dofs).n_elements(), this->mpi_communicator) << std::endl; } *Alberto Salvadori* Dipartimento di Ingegneria Civile, Architettura, Territorio, Ambiente e di Matematica (DICATAM) Universita` di Brescia, via Branze 43, 25123 Brescia Italy tel 030 3711239 fax 030 3711312 e-mail: alberto.salvad...@unibs.it web-pages: http://m4lab.unibs.it/faculty.html http://dicata.ing.unibs.it/salvadori On Wed, Jan 17, 2018 at 11:01 PM, Frohne, Joerg < fro...@mathematik.uni-siegen.de> wrote: > >>On 01/17/2018 02:45 PM, Frohne, Joerg wrote: > >> obviously this is a mistake. I checked the source files which we have > used for results in corresponding paper. > >> There I have found the following coding: > >> > >> resid_old = resid; > >> > >> resid_vector = system_rhs_newton; > >> resid_vector.compress(VectorOperation::insert); > >> > >> int is_my_set_changed = (active_set == active_set_old) ? 0 : > 1; > >> int num_changed = Utilities::MPI::sum(is_my_set_changed, > >> MPI_COMM_WORLD); > >> if (num_changed == 0 && resid < 1e-8) > >> break; > >> active_set_old = active_set; > >> > >> Unfortunately I have not been working with deal.ii for over two years > now. > >> For this reason I would be glad if someone else could fix this bug. > >> Otherwise I would need a short manual how to do it by myself. > > >I can do that for you. Do I understand correctly that the only change > >that needs to happen is to move > > active_set_old = active_set; > >to *after* the if-statement? > > Exactly. > > Best, > Joerg > > -- > The deal.II project is located at http://www.dealii.org/ > For mailing list/forum options, see https://groups.google.com/d/ > forum/dealii?hl=en > --- > You received this message because you are subscribed to the Google Groups > "deal.II User Group" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to dealii+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- Informativa sulla Privacy: http://www.unibs.it/node/8155 -- The deal.II project is located at http://www.dealii.org/ For mailing list/forum options, see https://groups.google.com/d/forum/dealii?hl=en --- You received this message because you are subscribed to the Google Groups "deal.II User Group" group. To unsubscribe from this group and stop receiving emails from it, send an email to dealii+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.