38 std::vector<DenseVector<Real>> & left_basis_functions,
39 std::vector<DenseVector<Real>> & right_basis_functions,
40 std::vector<Real> & singular_values,
41 const dof_id_type num_modes,
42 const Real energy)
const
45#if !PETSC_VERSION_LESS_THAN(3, 14, 0)
53 dof_id_type local_rows = 0;
54 dof_id_type snapshot_size = 0;
55 dof_id_type global_rows = 0;
60 local_rows += row.second.size();
61 if (row.second.size())
62 snapshot_size = row.second[0].size();
64 global_rows = local_rows;
74 _communicator.get(), local_rows, PETSC_DECIDE, global_rows, snapshot_size, NULL, &mat));
78 dof_id_type local_beg = 0;
79 dof_id_type local_end = 0;
81 MatGetOwnershipRange(mat,
85 unsigned int counter = 0;
90 for (
const auto & snap : row.second)
92 std::vector<PetscInt> rows(snapshot_size, (counter++) + local_beg);
95 std::vector<PetscInt> columns(snapshot_size);
96 std::iota(std::begin(columns), std::end(columns), 0);
105 snap.get_values().data(),
111 LibmeshPetscCallA(
_communicator.get(), MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
112 LibmeshPetscCallA(
_communicator.get(), MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
117 LibmeshPetscCallA(
_communicator.get(), SVDSetOperators(svd, mat, NULL));
122 LibmeshPetscCallA(
_communicator.get(), DSSetParallel(ds, DS_PARALLEL_DISTRIBUTED));
126 LibmeshPetscCallA(
_communicator.get(), SVDSetType(svd, SVDTRLANCZOS));
130 LibmeshPetscCallA(
_communicator.get(), SVDSetImplicitTranspose(svd, PETSC_TRUE));
139 SVDSetDimensions(svd,
141 std::min(2 * num_modes, global_rows),
142 std::min(2 * num_modes, global_rows)));
145 LibmeshPetscCallA(
_communicator.get(), SVDSetFromOptions(svd));
152 LibmeshPetscCallA(
_communicator.get(), SVDGetConverged(svd, &nconv));
157 dof_id_type local_snapsize = 0;
162 u.init(snapshot_size, local_snapsize,
false, PARALLEL);
165 v.init(global_rows, local_rows,
false, PARALLEL);
167 left_basis_functions.clear();
168 right_basis_functions.clear();
169 singular_values.clear();
171 singular_values.resize(nconv);
173 for (PetscInt j = 0; j < nconv; ++j)
175 SVDGetSingularTriplet(svd, j, &singular_values[j], NULL, NULL));
181 left_basis_functions.resize(num_requested_modes);
182 right_basis_functions.resize(num_requested_modes);
183 for (PetscInt j = 0; j < cast_int<PetscInt>(num_requested_modes); ++j)
185 LibmeshPetscCallA(
_communicator.get(), SVDGetSingularTriplet(svd, j, NULL,
v.vec(), u.vec()));
186 u.localize(left_basis_functions[j].get_values());
187 v.localize(right_basis_functions[j].get_values());
193 libmesh_ignore(vname);
194 libmesh_ignore(left_basis_functions);
195 libmesh_ignore(right_basis_functions);
196 libmesh_ignore(singular_values);
197 libmesh_ignore(num_modes);
198 libmesh_ignore(energy);
204 const dof_id_type num_modes_compute,
205 const Real energy)
const
207 dof_id_type num_modes = 0;
210 std::size_t num_requested_modes =
211 std::min((std::size_t)num_modes_compute, singular_values.size());
213 std::vector<Real> ev_sum(singular_values.begin(), singular_values.begin() + num_requested_modes);
214 std::partial_sum(ev_sum.cbegin(),
217 [](Real sum, Real ev) { return sum + ev * ev; });
220 const Real threshold = energy;
221 for (num_modes = 0; num_modes < ev_sum.size(); ++num_modes)
222 if (ev_sum[num_modes] / ev_sum.back() > 1 - threshold)
225 return num_modes + 1;