13#ifndef _LEPNC_STEFANPME_TRANSIENT_HPP
14#define _LEPNC_STEFANPME_TRANSIENT_HPP
20#include <boost/timer/timer.hpp>
23#include <Eigen/Sparse>
80 std::string solver_type,
81 std::ostream & output = std::cout
88 const Eigen::VectorXd Xn
92 Eigen::VectorXd
apply_nonlinearity(
const Eigen::VectorXd& Y,
const std::string type)
const;
98 double Lp_MassLumped(
const Eigen::VectorXd Xh,
double p)
const;
101 double EnergyNorm(
const Eigen::VectorXd Xh)
const;
105 return double(_assembly_time) * pow(10, -9);
109 return double(_solving_time) * pow(10, -9);
113 return double(_itime[idx]) * pow(10, -9);
117 return _solving_error;
131 Eigen::MatrixXd diffusion_operator(
const size_t iT)
const;
134 Eigen::VectorXd load_operator_ml(
const double tps,
const size_t iT)
const;
138 Eigen::VectorXd residual_scheme(
const double dt,
const Eigen::VectorXd& Xh)
const;
148 const double _weight;
149 const std::string solver_type;
150 std::ostream & m_output;
153 std::vector<Eigen::MatrixXd> DiffT;
154 std::vector<Eigen::MatrixXd> MassT;
155 std::vector<Eigen::VectorXd> RightHandSideT;
158 size_t _assembly_time;
159 size_t _solving_time;
160 double _solving_error;
161 mutable std::vector<size_t> _itime = std::vector<size_t>(10, 0);
166LEPNC_StefanPME_Transient::LEPNC_StefanPME_Transient(
LEPNCCore &nc,
tensor_function_type kappa,
size_t deg_kappa,
source_function_type source,
BoundaryConditions BC,
solution_function_type exact_solution,
grad_function_type grad_exact_solution,
TestCaseNonLinearity::nonlinearity_function_type zeta,
double weight, std::string solver_type, std::ostream & output)
169 _deg_kappa(deg_kappa),
172 exact_solution(exact_solution),
173 grad_exact_solution(grad_exact_solution),
176 solver_type(solver_type),
179 m_output <<
"[LEPNC_StefanPME_Transient] Initializing" << std::endl;
185 RightHandSideT.resize(mesh->
n_cells());
186 for (
size_t iT = 0; iT < mesh->
n_cells(); iT++) {
190 DiffT[iT] = diffusion_operator(iT);
191 MassT[iT] = Eigen::MatrixXd::Zero(n_local_dofs, n_local_dofs);
193 MassT[iT].bottomRightCorner(n_edgesT, n_edgesT) = _weight * (measT / n_edgesT) * Eigen::MatrixXd::Identity(n_edgesT, n_edgesT);
200 boost::timer::cpu_timer timer;
201 boost::timer::cpu_timer timerint;
203 size_t n_edges_dofs = mesh->
n_edges();
207 for (
size_t iT = 0; iT < mesh->n_cells(); iT++) {
208 RightHandSideT[iT] = dt * load_operator_ml(tps, iT) + MassT[iT]*nc.
nc_restr(Xn, iT);
212 constexpr double tol = 1e-8;
213 constexpr size_t maxiter = 400;
217 Eigen::VectorXd Xhprev = Eigen::VectorXd::Zero(n_cell_dofs + n_edges_dofs);
218 Eigen::VectorXd Xh = Eigen::VectorXd::Zero(n_cell_dofs + n_edges_dofs);
221 Eigen::VectorXd DirBC = Eigen::VectorXd::Zero(n_cell_dofs + n_edges_dofs);
222 for (
size_t ibF = 0; ibF < mesh->n_b_edges(); ibF++){
223 Edge* edge = mesh->b_edge(ibF);
224 if (m_BC.
type(*edge)==
"dir"){
225 size_t iF = edge->global_index();
229 DirBC(n_cell_dofs + iF) += quadrule.w * zeta(exact_solution(tps, quadrule.vector()),
"fct");
231 DirBC(n_cell_dofs + iF) += quadrule.w * exact_solution(tps, quadrule.vector());
235 DirBC(n_cell_dofs + iF) /= mesh->b_edge(ibF)->measure();
242 Eigen::VectorXd RES = residual_scheme(dt, Xhprev);
243 std::vector<double> residual(maxiter, 1.0);
244 residual[iter] = RES.norm();
246 while ( (iter < maxiter) && (residual[iter] > tol) ){
250 Eigen::SparseMatrix<double> GlobMat(n_edges_dofs, n_edges_dofs);
251 std::vector<Eigen::Triplet<double>> triplets_GlobMat;
252 Eigen::VectorXd GlobRHS = RES.tail(n_edges_dofs);
255 Eigen::SparseMatrix<double> ScMat(n_cell_dofs, n_edges_dofs);
256 std::vector<Eigen::Triplet<double>> triplets_ScMat;
257 Eigen::VectorXd ScRHS = Eigen::VectorXd::Zero(n_cell_dofs);
260 for (
size_t iT = 0; iT < mesh->n_cells(); iT++) {
261 Cell* cell = mesh->cell(iT);
262 size_t n_edgesT = cell->n_edges();
265 Eigen::VectorXd XTprev = nc.
nc_restr(Xhprev, iT);
268 for (
size_t i = 0; i < DimPoly<Cell>(1) + n_edgesT;
i++){
269 MatZetaprimeXTprev(
i,
i) = ZetaprimeXTprev(
i);
271 Eigen::MatrixXd MatT = dt * DiffT[iT] * MatZetaprimeXTprev + MassT[iT];
273 Eigen::MatrixXd ATF = MatT.topRightCorner(
DimPoly<Cell>(1), n_edgesT);
274 Eigen::MatrixXd AFT = MatT.bottomLeftCorner(n_edgesT,
DimPoly<Cell>(1));
275 Eigen::MatrixXd AFF = MatT.bottomRightCorner(n_edgesT, n_edgesT);
277 Eigen::PartialPivLU<Eigen::MatrixXd> invATT;
280 Eigen::MatrixXd invATT_ATF = invATT.solve(ATF);
282 Eigen::VectorXd invATT_RES_cell = invATT.solve(RES_cell);
285 Eigen::MatrixXd MatF = Eigen::MatrixXd::Zero(n_edgesT, n_edgesT);
286 Eigen::VectorXd bF = Eigen::VectorXd::Zero(n_edgesT);
287 MatF = AFF - AFT * invATT_ATF;
288 bF = - AFT * invATT_RES_cell;
292 for (
size_t i = 0; i < DimPoly<Cell>(1);
i++){
294 for (
size_t j = 0;
j < n_edgesT;
j++){
295 size_t jGlobal = cell->edge(
j)->global_index();
296 triplets_ScMat.emplace_back(iGlobal, jGlobal, invATT_ATF(
i,
j));
301 for (
size_t i = 0;
i < n_edgesT;
i++){
302 size_t iGlobal = cell->edge(
i)->global_index();
303 for (
size_t j = 0;
j < n_edgesT;
j++){
304 size_t jGlobal = cell->edge(
j)->global_index();
305 triplets_GlobMat.emplace_back(iGlobal, jGlobal, MatF(
i,
j));
307 GlobRHS(iGlobal) += bF(
i);
312 GlobMat.setFromTriplets(std::begin(triplets_GlobMat), std::end(triplets_GlobMat));
313 ScMat.setFromTriplets(std::begin(triplets_ScMat), std::end(triplets_ScMat));
319 size_t n_edge_unknowns = mesh->n_edges() - m_BC.
n_dir_edges();
320 Eigen::SparseMatrix<double>
A = GlobMat.topLeftCorner(n_edge_unknowns, n_edge_unknowns);
321 Eigen::VectorXd B = GlobRHS.head(n_edge_unknowns);
324 Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > solver;
326 Eigen::VectorXd dX_edge_unknowns = solver.solve(B);
328 Eigen::VectorXd dX = Eigen::VectorXd::Zero(n_cell_dofs + n_edges_dofs);
329 dX.segment(n_cell_dofs, n_edge_unknowns) = dX_edge_unknowns;
330 dX.head(n_cell_dofs) = ScRHS - ScMat * dX.tail(n_edges_dofs);
335 Xh.head(n_cell_dofs + n_edge_unknowns) = relax*dX.head(n_cell_dofs + n_edge_unknowns) + Xhprev.head(n_cell_dofs + n_edge_unknowns);
339 Eigen::VectorXd RES_temp = residual_scheme(dt, Xh);
340 double residual_temp = RES_temp.norm();
341 if (iter > 1 && residual_temp > 10*residual[iter-1]){
347 relax = std::min(1.0, 1.2*relax);
351 residual[iter] = residual_temp;
354 m_output <<
" ...Iteration: " << iter <<
"; residual = " << residual[iter] <<
"; relax = "<< relax <<
"\n";
373 Eigen::VectorXd ZetaY;
378 }
else if (type ==
"der" || type ==
"nlin"){
379 ZetaY = Eigen::VectorXd::Ones(Y.size());
381 m_output <<
"type unknown in apply_nonlinearity: " << type <<
"\n";
387 size_t n_cell_dofs = 0;
393 size_t n_edges_dofs = Y.size() - n_cell_dofs;
397 for (
size_t i = 0;
i < n_cell_dofs;
i++){
398 ZetaY(
i) = zeta(Y(
i), type);
400 }
else if (_weight == 1){
401 for (
size_t i = n_cell_dofs;
i < n_cell_dofs + n_edges_dofs;
i++){
402 ZetaY(
i) = zeta(Y(
i), type);
405 for (
size_t i = 0;
i < n_cell_dofs + n_edges_dofs;
i++){
406 ZetaY(
i) = zeta(Y(
i), type);
419Eigen::MatrixXd LEPNC_StefanPME_Transient::diffusion_operator(
const size_t iT)
const {
422 Cell* cell = mesh->cell(iT);
423 const size_t n_edgesT = cell->n_edges();
429 std::function<Eigen::Matrix2d(
double,
double)> kappaT = [&](
double x,
double y){
430 return kappa(x, y, cell);
434 size_t doe = 2 + _deg_kappa;
438 std::vector<Eigen::Matrix2d> kappaT_quadT(quadT.size());
439 std::transform(quadT.begin(), quadT.end(), kappaT_quadT.begin(),
440 [&kappaT](
QuadratureNode qr) -> Eigen::MatrixXd { return kappaT(qr.x, qr.y); });
442 return nc.
gram_matrix(Dnc_phiT_quadT, Dnc_phiT_quadT, local_dofs, local_dofs, quadT,
true, kappaT_quadT);
450Eigen::VectorXd LEPNC_StefanPME_Transient::load_operator_ml(
const double tps,
const size_t iT)
const {
453 Cell* cell = mesh->cell(iT);
454 size_t n_edgesT = cell->n_edges();
458 if (MassT.size() < iT ||
size_t(MassT[iT].rows()) != local_dofs){
459 m_output <<
"Called load_operator_ml without creating MassT[iT]\n";
462 Eigen::VectorXd fvec = Eigen::VectorXd::Zero(
DimPoly<Cell>(1) + n_edgesT);
463 for (
size_t i = 0;
i < local_dofs;
i++){
470 fvec(
i) = source(tps, node, cell);
473 Eigen::VectorXd load = MassT[iT] * fvec;
481 if (cell->is_boundary()){
482 for (
size_t ilF = 0; ilF < cell->n_edges(); ilF++) {
483 Edge* edge = cell->edge(ilF);
484 if (m_BC.
type(*edge)==
"neu"){
485 if (edge->is_boundary()){
486 const auto& nTF = cell->edge_normal(ilF);
489 return zeta(exact_solution(tps, p),
"der") * nTF.dot(kappa(p.x(),p.y(),cell) * grad_exact_solution(tps, p,cell));
506Eigen::VectorXd LEPNC_StefanPME_Transient::residual_scheme(
const double dt,
const Eigen::VectorXd& Xh)
const{
513 for (
size_t iT = 0; iT < mesh->
n_cells(); iT++){
515 size_t n_edgesT = cell->
n_edges();
517 Eigen::VectorXd XT = nc.
nc_restr(Xh, iT);
520 Eigen::VectorXd REST = RightHandSideT[iT] - (dt * DiffT[iT] * ZetaXT + MassT[iT] * XT);
522 for (
size_t ilE = 0; ilE < n_edgesT; ilE++){
523 size_t iE = cell->edge(ilE)->global_index();
542 for (
size_t iT = 0; iT < mesh-> n_cells(); iT++) {
543 Eigen::VectorXd XTF = nc.
nc_restr(Xh, iT);
544 value += XTF.transpose() * MassT[iT] * XTF;
555 for (
size_t iT = 0; iT < mesh-> n_cells(); iT++) {
556 Eigen::VectorXd XTF = nc.
nc_restr(Xh, iT);
558 Eigen::VectorXd XTF_powerp = (XTF.array().abs()).pow(p);
560 value += (MassT[iT] * XTF_powerp.matrix() ).sum();
563 return std::pow(value, 1.0/p);
570 for (
size_t iT = 0; iT < mesh-> n_cells(); iT++) {
571 Eigen::VectorXd XTF = nc.
nc_restr(Xh, iT);
572 value += XTF.transpose() * DiffT[iT] * XTF;
The BoundaryConditions class provides definition of boundary conditions.
Definition BoundaryConditions.hpp:45
const std::string type(const Edge &edge) const
Test the boundary condition of an edge.
Definition BoundaryConditions.cpp:41
const size_t n_dir_edges() const
Returns the number of Dirichlet edges.
Definition BoundaryConditions.hpp:70
Definition lepnccore.hpp:33
LEPNC scheme for diffusion equation .
Definition LEPNC_StefanPME_transient.hpp:60
std::function< double(double, std::string)> nonlinearity_function_type
type for nonlinear function
Definition TestCaseNonLinearity.hpp:48
Compute max and min eigenvalues of all matrices for i
Definition compute_eigs.m:5
Eigen::Vector2d VectorRd
Definition basis.hpp:55
const size_t DimPoly< Cell >(const int m)
Compute the size of the basis of 2-variate polynomials up to degree m.
Definition hybridcore.hpp:63
const Mesh * get_mesh() const
Returns a pointer to the mesh.
Definition hybridcore.hpp:201
Eigen::VectorXd apply_nonlinearity(const Eigen::VectorXd &Y, const std::string type) const
Compute non-linearity on vector (depends if weight=0, weight=1 or weight\in (0,1) )
Definition LEPNC_StefanPME_transient.hpp:366
Eigen::MatrixXd get_MassT(size_t iT) const
Mass matrix in cell iT.
Definition LEPNC_StefanPME_transient.hpp:124
Eigen::MatrixXd gram_matrix(const std::vector< Eigen::ArrayXd > &f_quad, const std::vector< Eigen::ArrayXd > &g_quad, const size_t &nrows, const size_t &ncols, const QuadratureRule &quad, const bool &sym, std::vector< double > L2weight={}) const
Definition lepnccore.hpp:517
LEPNC_StefanPME_Transient(LEPNCCore &nc, tensor_function_type kappa, size_t deg_kappa, source_function_type source, BoundaryConditions BC, solution_function_type exact_solution, grad_function_type grad_exact_solution, TestCaseNonLinearity::nonlinearity_function_type zeta, double weight, std::string solver_type, std::ostream &output=std::cout)
Constructor of the class.
Definition LEPNC_StefanPME_transient.hpp:166
Eigen::VectorXd iterate(const double tps, const double dt, const Eigen::VectorXd Xn)
Execute one time iteration.
Definition LEPNC_StefanPME_transient.hpp:198
Eigen::VectorXd nc_restr(const Eigen::VectorXd &Xh, size_t iT) const
Extract from a global vector Xh of unknowns the non-conforming unknowns corresponding to cell iT.
Definition lepnccore.hpp:678
double L2_MassLumped(const Eigen::VectorXd Xh) const
Mass-lumped L2 norm of a function given by a vector.
Definition LEPNC_StefanPME_transient.hpp:538
const std::vector< Eigen::ArrayXXd > grad_nc_basis_quad(const size_t iT, const QuadratureRule quad) const
Compute at the quadrature nodes, where are the cell basis functions.
Definition lepnccore.hpp:471
size_t get_nb_newton() const
number of Newton iterations
Definition LEPNC_StefanPME_transient.hpp:120
std::function< VectorRd(const double &, const VectorRd &, const Cell *)> grad_function_type
type for gradient
Definition LEPNC_StefanPME_transient.hpp:66
double EnergyNorm(const Eigen::VectorXd Xh) const
Discrete energy norm (associated to the diffusion operator)
Definition LEPNC_StefanPME_transient.hpp:566
std::function< Eigen::Matrix2d(const double, const double, const Cell *)> tensor_function_type
type for diffusion tensor (does not depend on time)
Definition LEPNC_StefanPME_transient.hpp:67
double get_solving_time() const
cpu time to solve the scheme
Definition LEPNC_StefanPME_transient.hpp:108
double get_itime(size_t idx) const
various intermediate assembly times
Definition LEPNC_StefanPME_transient.hpp:112
double Lp_MassLumped(const Eigen::VectorXd Xh, double p) const
Mass-lumped Lp norm of a function given by a vector.
Definition LEPNC_StefanPME_transient.hpp:551
double get_solving_error() const
residual after solving the scheme
Definition LEPNC_StefanPME_transient.hpp:116
const VectorRd ml_node(size_t iT, size_t i) const
Return the i'th nodal point in cell iT (for mass lumping)
Definition lepnccore.hpp:422
std::function< double(const double &, const VectorRd &, const Cell *)> source_function_type
type for source
Definition LEPNC_StefanPME_transient.hpp:65
double get_assembly_time() const
cpu time to assemble the scheme
Definition LEPNC_StefanPME_transient.hpp:104
std::function< double(const double &, const VectorRd &)> solution_function_type
type for solution
Definition LEPNC_StefanPME_transient.hpp:64
double measure() const
Return the Lebesgue measure of the Polytope.
Definition Polytope2D.hpp:76
Polytope< DIMENSION > Cell
Definition Polytope2D.hpp:151
Cell * cell(std::size_t index) const
get a constant pointer to a cell using its global index
Definition Mesh2D.hpp:178
size_t n_edges() const
Return the number of edges of the Polytope.
Definition Polytope2D.hpp:88
Polytope< 1 > Edge
A Face is a Polytope with object_dim = DIMENSION - 1.
Definition Polytope2D.hpp:147
std::size_t n_cells() const
number of cells in the mesh.
Definition Mesh2D.hpp:63
std::size_t n_edges() const
number of edges in the mesh.
Definition Mesh2D.hpp:61
std::vector< QuadratureNode > QuadratureRule
Definition quadraturerule.hpp:55
QuadratureRule generate_quadrature_rule(const Cell &T, const int doe, const bool force_split)
Generate quadrature rule on mesh element.
Definition quadraturerule.cpp:10
for j
Definition mmread.m:174
Definition ddr-klplate.hpp:27
Description of one node and one weight from a quadrature rule.
Definition quadraturerule.hpp:41