39 std::vector<DenseVector<Real>> & left_basis_functions,
40 std::vector<DenseVector<Real>> & right_basis_functions,
41 std::vector<Real> & singular_values,
42 const dof_id_type num_modes,
43 const Real energy)
const
46#if !PETSC_VERSION_LESS_THAN(3, 14, 0)
54 dof_id_type local_rows = 0;
55 dof_id_type snapshot_size = 0;
56 dof_id_type global_rows = 0;
61 local_rows += row.second.size();
62 if (row.second.size())
63 snapshot_size = row.second[0].size();
65 global_rows = local_rows;
75 _communicator.get(), local_rows, PETSC_DECIDE, global_rows, snapshot_size, NULL, &mat));
79 dof_id_type local_beg = 0;
80 dof_id_type local_end = 0;
82 MatGetOwnershipRange(mat,
86 unsigned int counter = 0;
91 for (
const auto & snap : row.second)
93 std::vector<PetscInt> rows(snapshot_size, (counter++) + local_beg);
96 std::vector<PetscInt> columns(snapshot_size);
97 std::iota(std::begin(columns), std::end(columns), 0);
106 snap.get_values().data(),
112 LibmeshPetscCallA(
_communicator.get(), MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
113 LibmeshPetscCallA(
_communicator.get(), MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
118 LibmeshPetscCallA(
_communicator.get(), SVDSetOperators(svd, mat, NULL));
123 LibmeshPetscCallA(
_communicator.get(), DSSetParallel(ds, DS_PARALLEL_DISTRIBUTED));
127 LibmeshPetscCallA(
_communicator.get(), SVDSetType(svd, SVDTRLANCZOS));
131 LibmeshPetscCallA(
_communicator.get(), SVDSetImplicitTranspose(svd, PETSC_TRUE));
140 SVDSetDimensions(svd,
142 std::min(2 * num_modes, global_rows),
143 std::min(2 * num_modes, global_rows)));
146 LibmeshPetscCallA(
_communicator.get(), SVDSetFromOptions(svd));
153 LibmeshPetscCallA(
_communicator.get(), SVDGetConverged(svd, &nconv));
158 dof_id_type local_snapsize = 0;
163 u.init(snapshot_size, local_snapsize,
false, PARALLEL);
166 v.init(global_rows, local_rows,
false, PARALLEL);
168 left_basis_functions.clear();
169 right_basis_functions.clear();
170 singular_values.clear();
172 singular_values.resize(nconv);
174 for (PetscInt j = 0; j < nconv; ++j)
176 SVDGetSingularTriplet(svd, j, &singular_values[j], NULL, NULL));
182 left_basis_functions.resize(num_requested_modes);
183 right_basis_functions.resize(num_requested_modes);
184 for (PetscInt j = 0; j < cast_int<PetscInt>(num_requested_modes); ++j)
186 LibmeshPetscCallA(
_communicator.get(), SVDGetSingularTriplet(svd, j, NULL,
v.vec(), u.vec()));
187 u.localize(left_basis_functions[j].get_values());
188 v.localize(right_basis_functions[j].get_values());
194 libmesh_ignore(vname);
195 libmesh_ignore(left_basis_functions);
196 libmesh_ignore(right_basis_functions);
197 libmesh_ignore(singular_values);
198 libmesh_ignore(num_modes);
199 libmesh_ignore(energy);
205 const dof_id_type num_modes_compute,
206 const Real energy)
const
208 dof_id_type num_modes = 0;
211 std::size_t num_requested_modes =
212 std::min((std::size_t)num_modes_compute, singular_values.size());
214 std::vector<Real> ev_sum(singular_values.begin(), singular_values.begin() + num_requested_modes);
215 std::partial_sum(ev_sum.cbegin(),
218 [](Real sum, Real ev) { return sum + ev * ev; });
221 const Real threshold = energy;
222 for (num_modes = 0; num_modes < ev_sum.size(); ++num_modes)
223 if (ev_sum[num_modes] / ev_sum.back() > 1 - threshold)
226 return num_modes + 1;