CArl
Code Arlequin / C++ implementation
FETI_operations_operations.cpp
Go to the documentation of this file.
1 #include "FETI_operations.h"
2 
3 namespace carl
4 {
5 // --- Null space / rigid body modes methods
6 void FETI_Operations::calculate_null_space_phi_0(const std::string& force_path)
7 {
8  // phi0 = - RC * (inv_RITRI_mat) * R^t* Force
9  homemade_assert_msg(m_bScratchFolderSet,"Scratch folder not set yet!");
10  homemade_assert_msg(m_bNullVecsSet,"Null space vectors not set yet!");
11  homemade_assert_msg(m_binvRITRIMatSet,"Null space matrices not set yet!");
12  homemade_assert_msg(m_bC_R_micro_MatrixSet,"Micro coupling matrix not set yet!");
13  homemade_assert_msg(m_bC_R_BIG_MatrixSet,"Macro coupling matrix not set yet!");
14 
15  // --- Declare / create the vectors
16  // phi(0)
17  VecCreate(m_comm.get(),&m_current_phi);
19  VecSetFromOptions(m_current_phi);
20 
21  // Force vector
22  Vec vec_force_PETSc;
23  VecCreate(m_comm.get(),&vec_force_PETSc);
24  read_PETSC_vector(vec_force_PETSc,force_path,m_comm.get());
25 
26  // Create the local auxiliary vectors
27  Vec aux_null_vec_input;
28  Vec aux_null_vec_output;
29 
30  VecCreateSeq(PETSC_COMM_SELF,m_null_nb_vecs,&aux_null_vec_input);
31  VecCreateSeq(PETSC_COMM_SELF,m_null_nb_vecs,&aux_null_vec_output);
32 
33  VecZeroEntries(aux_null_vec_input);
34  VecZeroEntries(aux_null_vec_output);
35 
36  // aux_vec_input = R^t * vec_force
37  // -> All the communications are done here!
38  // Cannot use VecMDot because "m_null_vecs" is a constant pointer ...
39  PetscScalar *dummy_array_input;
40  VecGetArray(aux_null_vec_input,&dummy_array_input);
41  for(int iii = 0; iii < m_null_nb_vecs; ++iii)
42  {
43  VecDot(vec_force_PETSc,m_null_vecs[iii],&dummy_array_input[iii]);
44  }
45  VecRestoreArray(aux_null_vec_input,&dummy_array_input);
46 
47  // aux_vec_output = inv_RITRI_mat * aux_vec_input
48  // -> Calculate aux_vec_output on the first proc, and then broadcast the value
49  /*
50  * Originally, this operation was done locally, but due to a syncing issue,
51  * we have to do it this way to avoid a "Value must the same in all processors" error
52  * when calling VecMAXPY below.
53  */
54  PETSC_MatMultScale_Bcast(m_inv_RITRI_mat,aux_null_vec_input,aux_null_vec_output,1);
55 
56  m_comm.barrier();
57 
58  // -> This should have no communications at all!
59  VecZeroEntries(m_current_phi);
60 
61  PetscScalar *dummy_array_output;
62  VecGetArray(aux_null_vec_output,&dummy_array_output);
63  VecMAXPY(m_current_phi,m_null_nb_vecs,dummy_array_output,m_null_coupled_vecs);
64  VecRestoreArray(aux_null_vec_output,&dummy_array_output);
65 
66  VecScale(m_current_phi,-1);
67 
68  // Cleanup
69  VecDestroy(&vec_force_PETSc);
70  VecDestroy(&aux_null_vec_input);
71  VecDestroy(&aux_null_vec_output);
72 
73  // Set flags
74  m_bSet_current_phi = true;
75 }
76 
77 // --- FETI steps methods
79 {
80  // `p(0)` is identical to `z(0)`, so just calculate the latter
81  this->calculate_z();
82 }
83 
85 {
86  /*
87  * If m_bUsingNullVecs == true :
88  * r(0) = ( C_1 * u_1,0 - C_2 * u_2,0 ) - C_1 * x_1(0) - C_2 * x_2(0)
89  *
90  * eles
91  * r(0) = ( C_1 * u_1,0 - C_2 * u_2,0 )
92  */
93 
94  // Common asserts
95  homemade_assert_msg(m_bC_R_micro_MatrixSet,"Micro coupling matrix not set yet!");
96  homemade_assert_msg(m_bC_R_BIG_MatrixSet,"Macro coupling matrix not set yet!");
97  homemade_assert_msg(m_bC_R_micro_MatrixSet,"Micro system dimensions not set yet!");
98  homemade_assert_msg(m_bC_R_BIG_MatrixSet,"Macro system dimensions not set yet!");
99  homemade_assert_msg(m_bSet_u_0,"Decoupled solution not set yet!");
100 
101  // Assert for only m_bUsingNullVecs == true
102  homemade_assert_msg(m_bSet_ext_solver_sol && m_bUsingNullVecs,"Ext. solver solutions not set yet!");
103 
104  // Create the vector
105  VecCreate(m_comm.get(),&m_current_residual);
107  VecSetFromOptions(m_current_residual);
108 
109  // - C_2 * u_0,2
111  VecScale(m_current_residual,-1);
112 
113  // C_1 * u_0,1
114  // --> r(0) = ( C_1 * u_0,1 - C_2 * u_0,2 )
116 
117  if(m_bUsingNullVecs)
118  {
119  Vec dummy_vec;
120  VecDuplicate(m_current_residual,&dummy_vec);
121 
122  // C_1 * x_1(0)
123  MatMult(m_C_R_BIG,m_ext_solver_sol_BIG,dummy_vec);
124 
125  // C_2 * x_2(0)
126  MatMultAdd(m_C_R_micro,m_ext_solver_sol_micro,dummy_vec,dummy_vec);
127 
128  // --> r(0) = ( C_1 * u_1,0 - C_2 * u_2,0 ) - C_1 * x_1(0) - C_2 * x_2(0)
129  VecAXPY(m_current_residual,-1,dummy_vec);
130  VecDestroy(&dummy_vec);
131  }
132 
133  // Set flag
135 }
136 
138 {
139  homemade_assert_msg(m_bSet_current_z,"Current 'z' not calculated yet!");
140  homemade_assert_msg(m_bSet_previous_p_ptr,"'p' vectors not set yet!");
141  homemade_assert_msg(m_bSet_previous_q_ptr,"'q' vectors not set yet!");
142 
143  // p(kkk+1) = z(kkk+1) + \sum ( beta(iii) * p(iii) ), iii = 0 ... kkk
144  // beta(iii) = - z(kkk+1).q(iii) / p(iii).q(iii)
145  // For simplicity, the signal was included in 'beta' - WATCH OUT FOR THE SIGNAL!
146  std::vector<PetscScalar> beta(m_kkk+1,0);
147  VecMDot(m_current_z,m_kkk+1,m_previous_q_ptr,beta.data());
148  for(int iii = 0; iii < m_kkk+1; ++iii)
149  {
150  beta[iii] = - beta[iii] / m_p_dot_q[iii];
151  }
152 
153  // p(kkk+1) = z(kkk+1)
154  VecDuplicate(m_current_z,&m_current_p);
155  VecCopy(m_current_z,m_current_p);
156 
157  // p(kkk+1) = z(kkk+1) + \sum ( beta(iii) * p(iii) )
158  VecMAXPY(m_current_p,m_kkk+1,beta.data(),m_previous_p_ptr);
159 
160  m_bSet_current_p = true;
161 }
162 
164 {
165  homemade_assert_msg(m_bC_R_micro_MatrixSet,"Micro coupling matrix not set yet!");
166  homemade_assert_msg(m_bC_R_BIG_MatrixSet,"Macro coupling matrix not set yet!");
167  homemade_assert_msg(m_bSet_ext_solver_sol,"Ext. solver solutions not set yet!");
168  homemade_assert_msg(m_bSet_previous_q_ptr,"'q' vectors not set yet!");
169 
170  // q(kkk) = C_1 * x_1(kkk) + C_2 * x_2(kkk)
173 }
174 
176 {
177  homemade_assert_msg(m_bSet_previous_q_ptr,"'q' vectors not set yet!");
178  homemade_assert_msg(m_bSet_previous_residual,"Previous 'r' not set yet!");
179  homemade_assert_msg(m_bSet_current_phi,"Current 'phi' not set yet!");
180  // Last assert is needed to guarantee that 'm_p_dot_q(kkk)' has been calculated
181 
182  // Calculate 'r(kkk + 1) = r(kkk) - gamma * q(kkk)'
183 
184  double dummy_double = - m_gamma;
187 
189 }
190 
192 {
193  /*
194  * Four possibilities:
195  * - m_bUsingNullVecs == false
196  * m_precond_type == BaseCGPrecondType::NO_PRECONDITIONER
197  * -> m_current_z = m_current_residual
198  *
199  * - m_bUsingNullVecs == false
200  * m_precond_type != BaseCGPrecondType::NO_PRECONDITIONER
201  * -> m_current_z = M_PC^-1 * m_current_residual
202  *
203  * - m_bUsingNullVecs == true
204  * m_precond_type == BaseCGPrecondType::NO_PRECONDITIONER
205  * -> m_current_z = M_proj * m_current_residual
206  *
207  * - m_bUsingNullVecs == true
208  * m_precond_type != BaseCGPrecondType::NO_PRECONDITIONER
209  * -> m_current_z = M_proj * M_PC^-1 * M_proj * m_current_residual
210  */
211 
213  homemade_assert_msg(m_bSet_current_residual,"Current residual not calculated yet!");
214 
215  if(m_bUsingNullVecs)
216  {
217  // Use projections!
219  {
220  // -> m_current_z = M_proj * M_PC^-1 * M_proj * m_current_residual
221  VecDuplicate(m_current_residual,&m_current_z);
222 
223  Vec dummy_vec, dummy_vec_bis;
224  VecDuplicate(m_current_residual,&dummy_vec);
225  VecDuplicate(m_current_residual,&dummy_vec_bis);
226 
227  // dummy_vec = M_proj * m_current_residual
228  this->apply_RB_projection(m_current_residual,dummy_vec);
229 
230  // dummy_vec_bis = M_PC^-1 * dummy_vec
231  this->apply_precond(dummy_vec,dummy_vec_bis);
232 
233  // m_current_z = M_proj * dummy_vec_bis
234  this->apply_RB_projection(dummy_vec_bis,m_current_z);
235 
236  VecDestroy(&dummy_vec);
237  VecDestroy(&dummy_vec_bis);
238 
239  // Set flag
240  m_bSet_current_z = true;
241  }
242  else
243  {
244  // -> m_current_z = M_proj * m_current_residual
245  VecDuplicate(m_current_residual,&m_current_z);
246 
248  m_bSet_current_z = true;
249  }
250  }
251  else
252  {
253  // Do not use projections!
255  {
256  // -> m_current_z = M_PC^-1 * m_current_residual
257  VecDuplicate(m_current_residual,&m_current_z);
258 
260  m_bSet_current_z = true;
261  }
262  // else, m_current_z = m_current_residual -> DO NOTHING!
263  }
264 }
265 
267 {
268  homemade_assert_msg(m_bSet_previous_p_ptr,"'p' vectors not set yet!");
269  homemade_assert_msg(m_bSet_previous_q_ptr,"'q' vectors not set yet!");
270  homemade_assert_msg(m_bSet_previous_phi,"Previous 'phi' not set yet!");
271 
272  // Calculate 'phi(kkk + 1) = phi(kkk) + gamma * p(kkk)'
273 
274  // gamma = rho(kkk) / ( p(kkk).q(kkk) )
275  VecDot(m_previous_p_ptr[m_kkk],m_previous_q_ptr[m_kkk],&m_p_dot_q[m_kkk]);
277 
278  // phi(kkk + 1) = phi(kkk) + gamma * p(kkk)
279  VecDuplicate(m_previous_phi,&m_current_phi);
281 
282  m_bSet_current_phi = true;
283 }
284 
286 {
287  homemade_assert_msg(m_bNullVecsSet,"Null space vectors not set yet!");
288  homemade_assert_msg(m_bSet_current_residual,"Current residual not calculated yet!");
289 
290  // Declare and create vectors
291  Vec dummy_seq_vec;
292  Vec dummy_seq_vec_bis;
293  VecCreateSeq(PETSC_COMM_SELF,m_null_nb_vecs,&dummy_seq_vec);
294  VecZeroEntries(dummy_seq_vec);
295  VecDuplicate(dummy_seq_vec,&dummy_seq_vec_bis);
296 
297  VecDuplicate(m_null_vecs[0],&m_current_rb_correction);
298  VecZeroEntries(m_current_rb_correction);
299 
300  // m_current_rb_correction = R * (inv_RITRI_mat) * RC^t * m_current_residual
301 
302  // dummy_seq_vec = RC^t * m_current_residual
303  // -> All the communications are done here!
304  PetscScalar *dummy_seq_array;
305  VecGetArray(dummy_seq_vec,&dummy_seq_array);
306  VecMDot(m_current_residual,m_null_nb_vecs,m_null_coupled_vecs,dummy_seq_array);
307 
308  VecRestoreArray(dummy_seq_vec,&dummy_seq_array);
309 
310  // dummy_seq_vec_bis = inv_RITRI_mat * dummy_seq_vec
311  /*
312  * Originally, this operation was done locally, but due to a syncing issue,
313  * we have to do it this way to avoid a "Value must the same in all processors" error
314  * when calling VecMAXPY below.
315  */
316  PETSC_MatMultScale_Bcast(m_inv_RITRI_mat,dummy_seq_vec,dummy_seq_vec_bis,1);
317 
318  m_comm.barrier();
319 
320  // m_current_rb_correction = sum ( dummy_seq_vec_bis[i] * m_null_vecs[i])
321  // -> This should have no communications at all!
322  VecGetArray(dummy_seq_vec_bis,&dummy_seq_array);
323  VecMAXPY(m_current_rb_correction,m_null_nb_vecs,dummy_seq_array,m_null_vecs);
324  VecRestoreArray(dummy_seq_vec_bis,&dummy_seq_array);
325 
326  // Cleanup
327  VecDestroy(&dummy_seq_vec);
328  VecDestroy(&dummy_seq_vec_bis);
329 
330  // Set flag
332 }
333 
335 {
336  homemade_assert_msg(m_bSet_current_residual,"Current residual not calculated yet!");
337  homemade_assert_msg(m_bSet_current_z,"Current 'z' not calculated yet!");
338  if(m_bUsingNullVecs)
339  homemade_assert_msg(m_bSet_current_RB_correction && m_bUsingNullVecs,"Current RB modes correction not calculated yet!");
340 
341  // --- Calculate the values
342  // rho(kkk+1)
344  {
346  } else {
348  }
349 
350  // RB_corr(kkk+1)
351  if(m_bUsingNullVecs)
352  {
354  }
355 
356  // gamma(kkk)
357  VecDot(m_previous_p_ptr[m_kkk],m_previous_q_ptr[m_kkk],&m_p_dot_q[m_kkk]);
358 
359  // Set flags
360  m_bCalculatedScalar = true;
361 }
362 
364 {
365  homemade_assert_msg(m_bSet_ext_solver_sol,"Ext. solver solutions not set yet!");
366  homemade_assert_msg(m_bSet_u_0,"Decoupled solution not set yet!");
367  homemade_assert_msg(m_bSet_current_RB_correction && m_bUsingNullVecs,"RB modes correction not set yet!");
368 
369  // Set the solution vectors
370  VecDuplicate(m_u_0_micro,&m_coupled_sol_micro);
371  VecDuplicate(m_u_0_BIG,&m_coupled_sol_BIG);
372 
373  // u_1 = - x_1(FINAL) + u_0,1
375 
376  // u_2 = x_2(FINAL) + u_0,2
378 
379  // Add rigid body modes correction, if needed
380  if(m_bUsingNullVecs)
381  {
382  switch (m_RB_modes_system)
383  {
384  case RBModesSystem::MACRO :
386  break;
387 
388  case RBModesSystem::MICRO :
390  break;
391  }
392  }
393 
394  // Set flags
395  m_bCoupled_sols_set = true;
396 }
397 
398 IterationStatus FETI_Operations::check_convergence(double rel_residual_conv, double abs_residual_conv, int max_iter_div, double rel_residual_div, double rb_modes_conv)
399 {
400  homemade_assert_msg(m_bCalculatedScalar,"Scalar quantities not calculated yet!");
401 
402  m_abs_residual_conv = abs_residual_conv;
403  m_rel_residual_conv = rel_residual_conv;
404  m_rb_modes_conv = rb_modes_conv;
405  m_rel_residual_div = rel_residual_div;
406  m_max_iter_div = max_iter_div;
407 
408  // Check the iteration divergence
409  if(m_kkk == m_max_iter_div) // Iteration divergence
410  {
411  m_bDivIter = true;
412  }
413 
414  // Check the residual convergence / divergence
415  if(m_current_rho > 0)
416  {
417  // Check the residual convergence
418  if(m_current_rho < m_abs_residual_conv) // Absolute convergence
419  {
420  m_bConvResidualAbs = true;
421  }
422 
423  if(m_current_rho < m_rel_residual_conv * m_rho_0) // Relative convergence
424  {
425  m_bConvResidualRel = true;
426  }
427 
428  // Check the residual divergence
429  if(m_current_rho > m_rel_residual_div * m_rho_0) // Relative divergence
430  {
431  m_bDivResidualRel = true;
432  }
433  } else {
434  // There's something wrong ...
435  m_bDivResidualNeg = true;
436  }
437 
438  // Check the rigid body modes correction convergence
439  if(m_bUsingNullVecs)
440  {
442  {
443  m_bConvRBCorrRel = true;
444  }
445  } else {
446  // Short-circuit this boolean
447  m_bConvRBCorrRel = true;
448  }
449 
450  // Possible cases:
451  // - Any diverged flag is true: diverged!
452  // - Both the RB modes correction AND one of the residual convergence flags are true: converged!
453  // - All flags false: continue iterating!
454 
457 
459  if(m_bDiv) {
460  output_status = IterationStatus::DIVERGED;
461  } else if(m_bConv) {
462  output_status = IterationStatus::CONVERGED;
463  } else {
464  output_status = IterationStatus::ITERATING;
465  }
466 
467  return output_status;
468 }
469 
470 }
double m_abs_residual_conv
Absolute residual convergence.
Vec m_current_residual
Current residual vector, r(kkk+1) (r(0) for the initialization)
bool m_bC_RR_MatrixSet
Mediator - mediator coupling matrix has been set?
double m_rho_0
Double containing the initial rho(0)
PetscInt m_null_nb_vecs
Number of null space vectors.
bool m_bSet_u_0
Have the u_0 vectors been set?
bool m_bConvResidualRel
The residual converged? (relative to initial value)
bool m_bSet_previous_residual
Have the previous r(kkk) vector been set?
Vec m_previous_phi
Previous Lagrange multipliers / solution, phi(kkk)
double m_previous_RB_mode_corr
Double containing the previous RB_mode_corr(kkk)
bool m_binvRITRIMatSet
Have the inv(RI^T * RI) matrix been set?
void calculate_q()
Calculate the current q(kkk) vector.
double m_gamma
Double containing the value of rho(kkk) / p(kkk) . q(kkk)
Mat m_C_R_BIG
Mediator - macro system coupling matrix.
void calculate_null_space_phi_0(const std::string &force_path)
Calculate the inital solution, .
bool m_bConv
Did the solver converge?
double m_rel_residual_conv
Relative residual convergence (relative to initial value)
Vec m_ext_solver_sol_micro
Micro model external solver solution.
bool m_bDivIter
The number of iterations diverged?
Vec m_u_0_BIG
Solution of the decoupled macro model.
void calculate_z()
Calculate the current z(kkk+1) vector.
Vec m_coupled_sol_micro
Coupled system solution for the micro model.
void calculate_phi()
Calculate the current phi(kkk+1) solution vector.
bool m_bC_R_BIG_MatrixSet
Mediator - macro coupling matrix has been set?
void calculate_scalar_data()
Calculate the scalar quantities.
Vec * m_previous_p_ptr
Pointer to the previous p vectors, p(0 ... kkk)
Mat m_inv_RITRI_mat
Matrix , used in some projectors.
int m_max_iter_div
Number of iterations divergence.
void calculate_initial_p()
Calculate the initial p(0) vector.
bool m_bSet_current_RB_correction
Have the RB modes correction RB_corr(kkk+1) vector been set?
bool m_bCalculatedScalar
Calculated the current iterations scalar data?
Vec m_u_0_micro
Solution of the decoupled micro model.
bool m_bDivResidualNeg
The residual is negative? (more usefull for debugging, really)
Vec m_current_z
Current z(kkk+1) (z(0) for the initialization)
void calculate_coupled_solution()
Calculate the final coupled solution.
Vec m_current_rb_correction
Current rigid body modes correction, RB_corr(kkk+1) (RB_corr(0) for the initialization) ...
bool m_bScratchFolderSet
Have the scratch folder been set?
Mat m_C_R_micro
Mediator - micro system coupling matrix.
bool m_bSet_previous_p_ptr
Have the previous p vectors, p(0 ... kkk), been set?
void calculate_rb_correction()
Calculate the rigid body modes corrections.
bool m_bSet_current_z
Have the current z(kkk+1) vector been set?
double m_current_RB_mode_corr
Double containing the current RB_mode_corr(kkk+1)
double m_rb_modes_conv
Relative RB correction convergence (relative to previous value)
Vec * m_previous_q_ptr
Pointer to the previous q vectors, q(0 ... kkk)
void PETSC_MatMultScale_Bcast(Mat mat_seq, Vec vec_seq_in, Vec vec_seq_out, double a_const)
double m_previous_rho
Double containing the previous rho(kkk)
bool m_bDiv
Did the solver diverge?
void calculate_r()
Calculate the current r(kkk+1) residual vector.
bool m_bSet_current_residual
Have the current r(kkk+1) vector been set?
IterationStatus check_convergence(double rel_residual_conv, double abs_residual_conv, int max_iter_div, double rel_residual_div, double rb_modes_conv=-1)
Check the convergence.
void calculate_p()
Calculate the current p(kkk+1) vector.
Vec m_coupled_sol_BIG
Coupled system solution for the macro model.
std::vector< double > m_p_dot_q
Vector containing the p.q scalar products.
RBModesSystem m_RB_modes_system
Which model is associated to the RB modes? Default: RBModesSystem::MICRO.
bool m_bSet_previous_q_ptr
Have the previous q vectors, q(0 ... kkk), been set?
bool m_bConvRBCorrRel
The RB correction converged? (relative to previous value)
libMesh::Parallel::Communicator & m_comm
Communicator.
IterationStatus
Definition: common_enums.h:41
Vec m_ext_solver_sol_BIG
Macro model external solver solution.
bool m_bConvResidualAbs
The residual converged? (absolute)
double m_rel_residual_div
Relative residual divergence (relative to initial value)
bool m_bSet_ext_solver_sol
Have the external solvers solutions been set vectors been set?
bool m_bC_R_micro_MatrixSet
Mediator - micro coupling matrix has been set?
bool m_bSet_current_p
Have the current p(kkk+1) vector been set?
Vec m_current_phi
Current Lagrange multipliers / solution, phi(kkk+1) (phi(0) for the initialization) ...
#define homemade_assert_msg(asserted, msg)
Definition: common_header.h:63
BaseCGPrecondType m_precond_type
Preconditioner type. Default: BaseCGPrecondType::NO_PRECONDITIONER.
bool m_bSet_previous_phi
Have the previous Lagrange multipliers / solution phi(kkk) been set?
void apply_RB_projection(Vec vec_in, Vec vec_out)
Apply the rigid body modes projection operation.
bool m_bCoupled_sols_set
Have the coupled solutions been set yet?
Vec m_null_coupled_vecs[maxVecLimit]
Null space vectors times the coupling matrix.
bool m_bDivResidualRel
The residual diverged? (relative to initial value)
Vec m_previous_residual
Previous residual vector, r(kkk)
int m_kkk
Current iteration index.
void read_PETSC_vector(libMesh::PetscVector< libMesh::Number > &input_vec, const std::string &filename)
bool m_bSet_current_phi
Have the current Lagrange multipliers / solution phi(kkk+1) been set?
void apply_precond(Vec vec_in, Vec vec_out)
Common interface to the preconditionners.
Vec m_current_p
Current p(kkk+1) (p(0) for the initialization)
void calculate_initial_r()
Calculate the inital residual vector, r(0)
Vec m_null_vecs[maxVecLimit]
Null space vectors.
double m_current_rho
Double containing the current rho(kkk+1)
bool m_bUsingNullVecs
Do we need to use the null space vectors?
bool m_bNullVecsSet
Have the null space vectors been set?