Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05ee77fd58 | ||
|
|
b1ab80e455 |
+48
-14
@@ -65,7 +65,7 @@ protected:
|
||||
HypreSmoother M_prec; // Preconditioner for the mass matrix M
|
||||
|
||||
CGSolver T_solver; // Implicit solver for T = M + dt K
|
||||
HypreSmoother T_prec; // Preconditioner for the implicit solver
|
||||
HypreBoomerAMG T_prec; // Preconditioner for the implicit solver
|
||||
|
||||
double alpha, kappa;
|
||||
|
||||
@@ -353,7 +353,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
}
|
||||
oper.SetParameters(u);
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_ADIOS2
|
||||
@@ -414,6 +413,7 @@ ConductionOperator::ConductionOperator(ParFiniteElementSpace &f, double al,
|
||||
T_solver.SetPrintLevel(0);
|
||||
T_solver.SetPreconditioner(T_prec);
|
||||
|
||||
T_prec.SetPrintLevel(0);
|
||||
SetParameters(u);
|
||||
}
|
||||
|
||||
@@ -430,19 +430,53 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
|
||||
void ConductionOperator::ImplicitSolve(const double dt,
|
||||
const Vector &u, Vector &du_dt)
|
||||
{
|
||||
// Solve the equation:
|
||||
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
|
||||
// for du_dt
|
||||
if (!T)
|
||||
{
|
||||
T = Add(1.0, Mmat, dt, Kmat);
|
||||
current_dt = dt;
|
||||
// Here we use Picard iterations to solve a nonlinear equation
|
||||
// for the Runge-Kutta stage vector k,
|
||||
//
|
||||
// M*k = N(u+dt*k) (1)
|
||||
//
|
||||
// for nonlinear operator N. We assume N can be written as
|
||||
//
|
||||
// N(u+dt*k) := L[u+dt*k](u+dt*k) + f(t)
|
||||
//
|
||||
// where L is a matrix-valued operator evaluated at u+dt*k and f(t)
|
||||
// a (potentially zero) time-dependent forcing vector. (1) can be
|
||||
// rewritten as a fixed-point equation
|
||||
//
|
||||
// x = (M - dt*L[x])^{-1} (Mu + f) (2)
|
||||
//
|
||||
// where x := u + dt*k, which can be solved using a Picard iteration,
|
||||
// where a function G(x) = x is solved via iteraitons x_{k+1} = G(x_k).
|
||||
|
||||
double tol = 1e-6;
|
||||
int maxiter = 100;
|
||||
|
||||
// Right-hand side for nonlinear iteration
|
||||
Mmat.Mult(u, z); // Add forcing function if one exists
|
||||
du_dt = u; // Set u as initial guess for x (2)
|
||||
Vector temp(u); // Vector to measure error
|
||||
temp = u;
|
||||
double error = 1;
|
||||
int iter = 0;
|
||||
while (error > tol) {
|
||||
iter ++;
|
||||
this->SetParameters(du_dt); // Update nonlinear operator L[x]
|
||||
T = Add(1.0, Mmat, dt, Kmat); // Form matrix (M - dt*L[x])
|
||||
T_solver.SetOperator(*T);
|
||||
T_solver.Mult(z, du_dt); // Apply (M - dt*L[x])^{-1}
|
||||
temp -= du_dt; // Measure error
|
||||
error = std::sqrt(InnerProduct(MPI_COMM_WORLD, temp, temp));
|
||||
temp = du_dt;
|
||||
if (iter >= maxiter) {
|
||||
mfem_warning("Nonlinear iteration did not converge!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
MFEM_VERIFY(dt == current_dt, ""); // SDIRK methods use the same dt
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg();
|
||||
T_solver.Mult(z, du_dt);
|
||||
|
||||
// Above we solved for x = u + dt*k, where k is the desired update
|
||||
// Map du_dt -> k.
|
||||
du_dt -= u;
|
||||
du_dt /= dt;
|
||||
}
|
||||
|
||||
void ConductionOperator::SetParameters(const Vector &u)
|
||||
@@ -483,4 +517,4 @@ double InitialTemperature(const Vector &x)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user