PreconditionSOR<SparseMatrix<double>> preconditioner;
preconditioner.initialize(system_matrix);
SolverControl sc(20000, 1e0, true, true);
SolverGMRES<Vector<double>>::AdditionalData additional_data;
additional_data.max_n_tmp_vectors = 1000;
additional_data.force_re_orthogonalization = true;
SolverGMRES<Vector<double>> A_direct(sc,additional_data);
A_direct.solve(system_matrix, solution, system_rhs, preconditioner);I can't get the GMRES solver to converge. The attached image "GMRES solution.jpg" shows what I get with GMRES using the code below, and "UMFPACK solution.jpg" shows what the original step-29 code using the UMFPACK solver generates.
SolverControl solver_control(1000, convergence_condition);
SparseILU<double>::AdditionalData additional_data(0, 100);
SparseILU<double> preconditioner_ilu;
preconditioner_ilu.initialize(system_matrix, additional_data);
unsigned int restart = 35;
SolverGMRES< Vector<double> >::AdditionalData gmres_additional_data(restart + 2);
SolverGMRES<Vector<double>> solver(solver_control, gmres_additional_data);
solver.solve(system_matrix, solution, system_rhs, preconditioner_ilu);
The GMRES solver does reduce the error by over 6 orders of magnitude (1.88354e+09/371.922 = 5e6) but that's as good as I got with the set of parameters I was working with. (Note that I changed the frequency in the *.prm file from 3e7 to 2e7 to make the solution a bit smoother. This helped GMRES to at least generate a solution that didn't look like numerical noise.)
DEAL:: Number of degrees of freedom: 206082
DEAL::Assembling system matrix... done (1.87201s)
convergence condition = 400
DEAL:GMRES::Solving linear system... Starting value 1.88354e+09
DEAL:GMRES::Convergence step 17 value 371.922
DEAL::done (59.2804s)
output_file = solution
DEAL::Generating output... done (28.3922s)
So far what you've seen is the solutions with the parameter file having the variable "Number of refinements" set to 6, which is what I got with the 8.3 code. But the 8.3 code I got from Timo's VirtualBox image had this set to 5. When I set it to 5 and run it with the same GMRES code as shown above, I can reduce the error from 7.44224e+14 to 40. Pretty good, but the solution is mostly noise (see "GMRES solution with 5 refinement steps.jpg").
DEAL:GMRES::Solving linear system... Starting value 7.44224e+14
DEAL:GMRES::Re-orthogonalization enabled at step 15
DEAL:GMRES::Convergence step 210 value 39.9634
To try to understand what could be going on I exported the sparsity pattern and plotted it in "sparsity pattern.jpg". It seems well formed, at least as far as I can tell. I looked at what was going on at about the center of the matrix and decided to see how many non-zero entries there were in the matrix and how "wide" the triangular spread is. I generated the data below for the 6 refinement steps case. Note that the size of the matrix is 206082x206082.
All rows have 18 non-zero entries. Some of the rows are quite tight (just 25 indexes separating the non-zero entries) , while some are quite wide (over 35k entries separating the non-zero entries. Does this mean anything?
At this point I'm lost as to what I should do and I need some suggestions. I'll attach the code and parameter file I'm using. I believe I've tried all of the suggestions that have been given to me so far, but if anyone wants to try to outline a range of parameters or approaches to try, I'll do so.
Thanks for reading, Jason
1st column = row #
2nd column = # of non-zero entries in row
3rd column = max non-zero column index - min non-zero column index
(this is basically how wide the sparse matrix is)
100000 18 73
100001 18 73
100002 18 35657
100003 18 35657
100004 18 35641
100005 18 35641
100006 18 41
100007 18 41
100008 18 25
100009 18 25
100010 18 35641
100011 18 35641
100012 18 37001
100013 18 37001
100014 18 25
100015 18 25
100016 18 1385
100017 18 1385
100018 18 41
100019 18 41
100020 18 25
100021 18 25
100022 18 73
100023 18 73
100024 18 57
100025 18 57
100026 18 25
100027 18 25
100028 18 1385
100029 18 1385
100030 18 57
100031 18 57
100032 18 1417
100033 18 1417
100034 18 137
100035 18 137
100036 18 57
100037 18 57
100038 18 105
100039 18 105
100040 18 25
when U is decomposed into it's real and imaginary parts v=real(U) w=imag(U) we get
−ω2v−(co2−α2)Δv − 2coαΔw=0
−ω2w−(co2−α2)Δw+2coαΔv=0
So now we've got a loosely coupled set of equations instead of equations that
are only coupled through the boundary condition.
My problem now is how do I modify the step-29 code to take this coupling into account.
I somewhat blindly change the code to that shown below, but it hasn't made
any difference with the solver. Did I do it right?
double alpha = c / 100.0; // attenuation embedded into a complex speed of sound
// speed of sound = c-i*alpha
if (fe.system_to_component_index(i).first ==
fe.system_to_component_index(j).first)
{
// this part is unchanged
for (unsigned int q_point = 0; q_point<n_q_points; ++q_point)
cell_matrix(i, j) += (((fe_values.shape_value(i, q_point) *
fe_values.shape_value(j, q_point)) *
(-omega * omega)
+
(fe_values.shape_grad(i, q_point) *
fe_values.shape_grad(j, q_point)) *
(c * c - alpha * alpha)) *
fe_values.JxW(q_point));
}
else
{
// this is the part i added... am I doing something wrong???
double coeff = 2*c*alpha;
if (fe.system_to_component_index(i).first == 0) // real part?
coeff = -coeff;
unsigned int component_i = fe.system_to_component_index(i).first;
unsigned int component_j = fe.system_to_component_index(j).first;
for (unsigned int q_point = 0; q_point<n_q_points; ++q_point)
cell_matrix(i, j) +=
(fe_values.shape_grad(i, q_point)[component_i] *
fe_values.shape_grad(j, q_point)[component_j]) *
coeff *
fe_values.JxW(q_point);
}
I finally got the GMRES solver to converge to a good solution for step-29!
I'll paste in the parameters and the code that I used below. What finally got it to converge was to set the max_n_tmp_vectors of SolverGMRES::AdditionalData to 500 instead of 35. Someone had recommended using this parameter, but had suggested a value of 35. I got frustrated and cranked it up to 500 and I finally GMRES to converge to a good solution. I don't know what this does yet, but obviously I need to look into it more.
Thanks for everyone's help!
Next question:
The parameters below are requiring around 350 iteration steps. This is going to be too slow for most of my problems. However, my solutions will be run over a frequency range, usually about 200 frequencies, with the solution for the previous frequency being very similar to the solution for the next frequency. Is it possible to use the solution from a previous frequency to help speed the system convergence for the next frequency? Note that once all of the frequency dependent data is put into the problem, the dependence on omega w is going to be more complex than just the w^2 that shows up in the Helmholtz problem.
Jason
Focal distance = 0.3
Number of refinements = 5
c = 1.5e5
omega = 3.0e7
convergence_condition = .01
nmax_iterations= 1000
additional_diagional_terms = 200
max_n_tmp_vectors = 500
SolverControl solver_control(nmax_iterations, convergence_condition);
SparseILU<double>::AdditionalData additional_data(0, additional_diagional_terms);
SparseILU<double> preconditioner_ilu;
preconditioner_ilu.initialize(system_matrix, additional_data);
SolverGMRES< Vector<double> >::AdditionalData gmres_additional_data(max_n_tmp_vectors + 2);