https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PrintMatricesNSProblem.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "NonlinearSystemBase.h"
12#include "NS.h"
13#include "MooseMesh.h"
15#include "libmesh/nonlinear_solver.h"
16#include "libmesh/petsc_matrix.h"
17#include "libmesh/petsc_vector.h"
18#include "libmesh/dof_map.h"
19#include "libmesh/nonlinear_implicit_system.h"
20#include <petscmat.h>
21#include <slepceps.h>
22
24
27{
29 params.addRequiredParam<TagName>(
30 "pressure_mass_matrix", "The matrix tag name corresponding to the pressure mass matrix.");
31 params.addRequiredParam<TagName>(
32 "velocity_mass_matrix", "The matrix tag name corresponding to the velocity mass matrix.");
33 params.addParam<std::vector<TagName>>(
34 "augmented_lagrange_matrices",
35 {},
36 "Matrices corresponding to finite element weak forms used to create augmented Lagrange "
37 "perturbations. Example weak forms include volumetric grad-div and face jumps for "
38 "discontinuous Galerkin discretizations. This is a vector because, for example, a user may "
39 "pass one matrix that corresponds just to grad-div, another corresponding to face jumps, and "
40 "yet another corresponding to the sum of the two.");
41 params.addRequiredParam<NonlinearVariableName>("u", "The interior x-velocity variable");
42 params.addRequiredParam<NonlinearVariableName>("v", "The interior y-velocity variable");
43 params.addParam<NonlinearVariableName>(NS::pressure, "The pressure in the volume");
44 params.addParam<NonlinearVariableName>(NS::pressure + "_bar", "The pressure on the facets");
45 params.addParam<bool>("print", true, "Whether to print the matrices");
46 return params;
47}
48
50 : FEProblem(parameters),
51 _pressure_mass_matrix(getParam<TagName>("pressure_mass_matrix")),
52 _velocity_mass_matrix(getParam<TagName>("velocity_mass_matrix")),
53 _augmented_lagrange_matrices(getParam<std::vector<TagName>>("augmented_lagrange_matrices"))
54{
55 if (_communicator.size() > 1)
56 mooseError("This problem can only be used in serial");
57}
58
59void
61{
63
64 const bool print = getParam<bool>("print");
65
66 const bool has_p = isParamValid(NS::pressure);
67 const bool has_pbar = isParamValid(NS::pressure + "_bar");
68
69 auto & nl = getNonlinearSystemBase(0);
70 auto & dof_map = nl.dofMap();
71 auto & lm_mesh = mesh().getMesh();
72
73 const auto & u_var = nl.getVariable(0, getParam<NonlinearVariableName>("u"));
74 const auto & v_var = nl.getVariable(0, getParam<NonlinearVariableName>("v"));
75 const MooseVariableFieldBase * p_var = nullptr;
76 const MooseVariableFieldBase * pb_var = nullptr;
77 if (has_p)
78 p_var = &nl.getVariable(0, getParam<NonlinearVariableName>(NS::pressure));
79 if (has_pbar)
80 pb_var = &nl.getVariable(0, getParam<NonlinearVariableName>(NS::pressure + "_bar"));
81
82 // Retrieve DOF indices for each variable
83 std::vector<dof_id_type> u_indices, v_indices, p_vol_indices, pb_indices, vel_indices, p_indices;
84 dof_map.local_variable_indices(u_indices, lm_mesh, u_var.number());
85 dof_map.local_variable_indices(v_indices, lm_mesh, v_var.number());
86 if (has_p)
87 dof_map.local_variable_indices(p_vol_indices, lm_mesh, p_var->number());
88 if (has_pbar)
89 dof_map.local_variable_indices(pb_indices, lm_mesh, pb_var->number());
90 vel_indices = u_indices;
91 vel_indices.insert(vel_indices.end(), v_indices.begin(), v_indices.end());
92 p_indices = p_vol_indices;
93 if (has_pbar)
94 p_indices.insert(p_indices.end(), pb_indices.begin(), pb_indices.end());
95
96 // Retrieve mass matrices and system matrix
97 PetscMatrix<Number> vel_p_mat(_communicator), p_vel_mat(_communicator), p_mass_mat(_communicator),
98 vel_mass_mat(_communicator);
99 const auto pressure_mass_matrix_tag_id = getMatrixTagID(_pressure_mass_matrix);
100 auto & system_size_pressure_mass_matrix = nl.getMatrix(pressure_mass_matrix_tag_id);
101 const auto velocity_mass_matrix_tag_id = getMatrixTagID(_velocity_mass_matrix);
102 auto & system_size_velocity_mass_matrix = nl.getMatrix(velocity_mass_matrix_tag_id);
103 auto * const system_matrix =
104 dynamic_cast<PetscMatrix<Number> *>(&nl.nonlinearSolver()->system().get_system_matrix());
105 mooseAssert(system_matrix, "Must be a PETSc matrix");
106
107 auto write_matrix = [this](Mat write_mat, const std::string & mat_name)
108 {
109 PetscViewer matviewer;
110 LibmeshPetscCallA(
112 PetscViewerBinaryOpen(_communicator.get(), mat_name.c_str(), FILE_MODE_WRITE, &matviewer));
113 LibmeshPetscCallA(_communicator.get(), MatView(write_mat, matviewer));
114 LibmeshPetscCallA(_communicator.get(), PetscViewerDestroy(&matviewer));
115 };
116
117 auto do_vel_p =
118 [this,
119 write_matrix,
120 print,
121 &vel_indices,
122 &system_size_pressure_mass_matrix,
123 &system_size_velocity_mass_matrix,
124 system_matrix,
125 &vel_p_mat,
126 &p_vel_mat,
127 &p_mass_mat,
128 &vel_mass_mat](const auto & pressure_indices, const std::string & outer_matrix_name)
129 {
130 // Computes and writes to file the product LHS * M^-1 * RHS
131 auto compute_triple_product_matrix =
132 [this, print, write_matrix](PetscMatrix<Number> & lhs,
133 PetscMatrix<Number> & mass_matrix,
134 PetscMatrix<Number> & rhs,
135 const std::string & inner_matrix_name)
136 {
137 Mat I, M, Minv;
138
139 // Create the identity matrix
140 LibmeshPetscCall(MatCreateDense(_communicator.get(),
141 mass_matrix.local_m(),
142 mass_matrix.local_n(),
143 mass_matrix.m(),
144 mass_matrix.n(),
145 nullptr,
146 &I));
147 const PetscScalar one = 1.0;
148 for (const auto i : make_range(mass_matrix.row_start(), mass_matrix.row_stop()))
149 {
150 const auto petsc_i = cast_int<PetscInt>(i);
151 LibmeshPetscCall(MatSetValues(I, 1, &petsc_i, 1, &petsc_i, &one, INSERT_VALUES));
152 }
153 LibmeshPetscCall(MatAssemblyBegin(I, MAT_FINAL_ASSEMBLY));
154 LibmeshPetscCall(MatAssemblyEnd(I, MAT_FINAL_ASSEMBLY));
155
156 // Create Minv
157 LibmeshPetscCall(MatCreateDense(_communicator.get(),
158 mass_matrix.local_m(),
159 mass_matrix.local_n(),
160 mass_matrix.m(),
161 mass_matrix.n(),
162 nullptr,
163 &Minv));
164
165 // Factor mass matrix
166 LibmeshPetscCall(MatConvert(mass_matrix.mat(), MATDENSE, MAT_INITIAL_MATRIX, &M));
167 LibmeshPetscCall(MatLUFactor(M, nullptr, nullptr, nullptr));
168
169 // Solve for Minv
170 LibmeshPetscCall(MatMatSolve(M, I, Minv));
171
172 //
173 // Compute triple product and write the result
174 //
175
176 Mat triple_product_mat;
177 LibmeshPetscCall(MatMatMatMult(
178 lhs.mat(), Minv, rhs.mat(), MAT_INITIAL_MATRIX, PETSC_DEFAULT, &triple_product_mat));
179 LibmeshPetscCall(MatScale(triple_product_mat, -1));
180
181 PetscMatrix<Number> triple_product(triple_product_mat, _communicator);
182 if (print)
183 {
184 _console << std::endl << "Printing the '" << inner_matrix_name << "' matrix" << std::endl;
185 triple_product.print();
186 }
187 write_matrix(triple_product.mat(), inner_matrix_name + std::string(".mat"));
188
189 LibmeshPetscCall(MatDestroy(&triple_product_mat));
190 LibmeshPetscCall(MatDestroy(&I));
191 LibmeshPetscCall(MatDestroy(&M));
192 LibmeshPetscCall(MatDestroy(&Minv));
193 };
194
195 // Select blocks we care about (coupling between variables)
196 system_size_pressure_mass_matrix.create_submatrix(
197 p_mass_mat, pressure_indices, pressure_indices);
198 system_size_velocity_mass_matrix.create_submatrix(vel_mass_mat, vel_indices, vel_indices);
199 system_matrix->create_submatrix(vel_p_mat, vel_indices, pressure_indices);
200 system_matrix->create_submatrix(p_vel_mat, pressure_indices, vel_indices);
201
202 compute_triple_product_matrix(
203 vel_p_mat, p_mass_mat, p_vel_mat, outer_matrix_name + "_grad_div");
204 compute_triple_product_matrix(
205 p_vel_mat, vel_mass_mat, vel_p_mat, outer_matrix_name + "_div_grad");
206 };
207
208 if (has_p)
209 do_vel_p(p_vol_indices, "vel_p");
210 if (has_pbar)
211 do_vel_p(pb_indices, "vel_pb");
212 do_vel_p(p_indices, "vel_all_p");
213
214 // Print / write velocity block for each augmented Lagrange matrix
215 for (const auto & augmented_lagrange_name : _augmented_lagrange_matrices)
216 {
217 PetscMatrix<Number> jump_mat(_communicator);
218 const auto jump_matrix_tag_id = getMatrixTagID(augmented_lagrange_name);
219 auto & system_size_jump_matrix = nl.getMatrix(jump_matrix_tag_id);
220 system_size_jump_matrix.create_submatrix(jump_mat, vel_indices, vel_indices);
221 if (print)
222 {
223 _console << std::endl
224 << "Printing the jump matrix '" << augmented_lagrange_name << "'" << std::endl;
225 jump_mat.print();
226 }
227 write_matrix(jump_mat.mat(), augmented_lagrange_name + std::string(".mat"));
228 }
229}
const double M
registerMooseObject("NavierStokesTestApp", PrintMatricesNSProblem)
const ConsoleStream _console
virtual void onTimestepEnd() override
virtual MooseMesh & mesh() override
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
static InputParameters validParams()
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
MeshBase & getMesh()
unsigned int number() const
virtual void insert(libMesh::NumericVector< libMesh::Number > &vector)=0
A problem that solves and prints matrices used when solving the incompressible Navier-Stokes equation...
const TagName & _pressure_mass_matrix
The tag name of the pressure mass matrix.
static InputParameters validParams()
const TagName & _velocity_mass_matrix
The tag name of the velocity mass matrix.
virtual void onTimestepEnd() override
PrintMatricesNSProblem(const InputParameters &parameters)
const std::vector< TagName > & _augmented_lagrange_matrices
The tag name of the jump matrix.
virtual TagID getMatrixTagID(const TagName &tag_name) const
processor_id_type size() const
const Parallel::Communicator & _communicator
static const std::string pressure
Definition NS.h:57