Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trilinos parallel is_non_negative() function #12968

Merged
merged 4 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/news/changes/minor/20211202OConnor
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Changed: The function TrilinosWrappers::Vector::is_non_negative() now also works in parallel.
<br>
(Justin O'Connor, 2021/12/02)

28 changes: 9 additions & 19 deletions source/lac/trilinos_vector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -757,36 +757,26 @@ namespace TrilinosWrappers
bool
Vector::is_non_negative() const
{
// if this vector is a parallel one, then
// we need to communicate to determine
// the answer to the current
// function. this still has to be
// implemented
AssertThrow(local_size() == size(), ExcNotImplemented());
// get a representation of the vector and
// loop over all the elements
TrilinosScalar *start_ptr;
int leading_dimension;
int ierr = vector->ExtractView(&start_ptr, &leading_dimension);
AssertThrow(ierr == 0, ExcTrilinosError(ierr));

// TODO: This
// won't work in parallel like
// this. Find out a better way to
// this in that case.
const TrilinosScalar *ptr = start_ptr, *eptr = start_ptr + size();
bool flag = true;
TrilinosScalar * start_ptr = (*vector)[0];
const TrilinosScalar *ptr = start_ptr, *eptr = start_ptr + local_size();
unsigned int flag = 0;
while (ptr != eptr)
{
if (*ptr < 0.0)
{
flag = false;
flag = 1;
break;
}
++ptr;
}

return flag;
// in parallel, check that the vector
// is zero on _all_ processors.
const auto max_n_negative =
Utilities::MPI::max(flag, get_mpi_communicator());
return max_n_negative == 0;
}


Expand Down
92 changes: 92 additions & 0 deletions tests/mpi/trilinos_vector_non_negative.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// ---------------------------------------------------------------------
//
// Copyright (C) 2011 - 2020 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE.md at
// the top level directory of deal.II.
//
// ---------------------------------------------------------------------



// check correct behavior of checking all Trilinos vector entries are
// non-negative works for distributed vectors

#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>

#include <deal.II/lac/trilinos_vector.h>

#include <iostream>
#include <vector>

#include "../tests.h"


void
test()
{
const unsigned int myid = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
const unsigned int n_processes =
Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD);

// create a vector that consists of elements indexed from 0 to n
TrilinosWrappers::MPI::Vector vec;
{
IndexSet is(100 * n_processes);
is.add_range(100 * myid, 100 * myid + 100);
vec.reinit(is, MPI_COMM_WORLD);
}
AssertThrow(vec.local_size() == 100, ExcInternalError());
AssertThrow(vec.local_range().first == 100 * myid, ExcInternalError());
AssertThrow(vec.local_range().second == 100 * myid + 100, ExcInternalError());
for (unsigned int i = vec.local_range().first; i < vec.local_range().second;
++i)
vec(i) = i;
vec.compress(VectorOperation::insert);

// verify correctness so far
{
bool exact_non_negative = true;
AssertThrow(vec.is_non_negative() == exact_non_negative,
ExcInternalError());
}

if (vec.in_local_range(vec.size() / 2))
vec[vec.size() / 2] = -1;
{
bool exact_non_negative = false;
AssertThrow(vec.is_non_negative() == exact_non_negative,
ExcInternalError());
}

deallog << "OK" << std::endl;
}



int
main(int argc, char **argv)
{
Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);

unsigned int myid = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);


deallog.push(Utilities::int_to_string(myid));

if (myid == 0)
{
initlog();

test();
}
else
test();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

DEAL:0::OK