50 int main(
int argc,
char *argv[])
53 const char *mesh_file_1 =
"../../data/square-disc.mesh";
54 const char *mesh_file_2 =
"../../data/inline-quad.mesh";
56 bool visualization =
true;
59 double rel_tol = 1.e-8;
62 args.
AddOption(&mesh_file_1,
"-m1",
"--mesh",
64 args.
AddOption(&mesh_file_2,
"-m2",
"--mesh",
67 "Finite element order (polynomial degree) or -1 for"
68 " isoparametric space.");
69 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
71 "Enable or disable GLVis visualization.");
72 args.
AddOption(&r1_levels,
"-r1",
"--refine-serial",
73 "Number of times to refine the mesh uniformly in serial.");
74 args.
AddOption(&r2_levels,
"-r2",
"--refine-serial",
75 "Number of times to refine the mesh uniformly in serial.");
76 args.
AddOption(&rel_tol,
"-rt",
"--relative tolerance",
77 "Tolerance for Schwarz iteration convergence criterion.");
87 const int nmeshes = 2;
93 mesharr[0] =
new Mesh(mesh_file_1, 1, 1);
94 mesharr[1] =
new Mesh(mesh_file_2, 1, 1);
95 int dim = mesharr[0]->Dimension();
101 for (
int lev = 0; lev < r1_levels; lev++) { mesharr[0]->UniformRefinement(); }
102 for (
int lev = 0; lev < r2_levels; lev++) { mesharr[1]->UniformRefinement(); }
109 for (
int i = 0; i< nmeshes; i ++)
115 else if (mesharr[i]->GetNodes())
117 fecarr[i] = mesharr[i]->GetNodes()->OwnFEC();
118 cout <<
"Using isoparametric FEs: " << fecarr[0]->Name() << endl;
132 if (mesharr[0]->bdr_attributes.
Size())
136 fespacearr[0]->GetEssentialTrueDofs(ess_bdr, ess_tdof_list1);
139 if (mesharr[1]->bdr_attributes.
Size())
143 fespacearr[1]->GetEssentialTrueDofs(ess_bdr, ess_tdof_list2);
151 for (
int i = 0; i< nmeshes; i ++)
167 mesharr[0]->SetCurvature(order,
false, dim, Ordering::byNODES);
168 Vector mesh_nodes_1 = *mesharr[0]->GetNodes();
169 mesharr[1]->SetCurvature(order,
false, dim, Ordering::byNODES);
170 Vector mesh_nodes_2 = *mesharr[1]->GetNodes();
175 if (strcmp(mesh_file_1,
"../../data/square-disc.mesh") == 0 &&
176 strcmp(mesh_file_2,
"../../data/inline-quad.mesh") == 0 )
178 for (
int i = 0; i < mesh_nodes_2.
Size(); i++)
180 mesh_nodes_2(i) = 0.5 + 0.5*(mesh_nodes_2(i)-0.5);
182 mesharr[1]->SetNodes(mesh_nodes_2);
186 finder1.
Setup(*mesharr[0]);
187 finder2.
Setup(*mesharr[1]);
189 Array<int> ess_tdof_list1_int, ess_tdof_list2_int;
191 ess_tdof_list1, ess_tdof_list2,
192 ess_tdof_list1_int, ess_tdof_list2_int, dim);
196 const int number_boundary_1 = ess_tdof_list1_int.
Size(),
197 number_boundary_2 = ess_tdof_list2_int.
Size(),
198 number_true_1 = mesh_nodes_1.
Size()/
dim,
199 number_true_2 = mesh_nodes_2.
Size()/
dim;
201 MFEM_VERIFY(number_boundary_1 != 0 ||
202 number_boundary_2 != 0,
" Please use overlapping grids.");
204 Vector bnd1(number_boundary_1*dim);
205 for (
int i = 0; i < number_boundary_1; i++)
207 int idx = ess_tdof_list1_int[i];
208 for (
int d = 0; d <
dim; d++)
210 bnd1(i+d*number_boundary_1) = mesh_nodes_1(idx + d*number_true_1);
214 Vector bnd2(number_boundary_2*dim);
215 for (
int i = 0; i < number_boundary_2; i++)
217 int idx = ess_tdof_list2_int[i];
218 for (
int d = 0; d <
dim; d++)
220 bnd2(i+d*number_boundary_2) = mesh_nodes_2(idx + d*number_true_2);
224 Vector interp_vals1(number_boundary_1), interp_vals2(number_boundary_2);
250 int NiterSchwarz = 100;
253 for (
int i = 0; i < nmeshes; i ++)
263 a_ar[0]->FormLinearSystem(ess_tdof_list1, x1, *b_ar[0], A1, X1, B1);
264 a_ar[1]->FormLinearSystem(ess_tdof_list2, x2, *b_ar[1], A2, X2, B2);
269 PCG(*A1, M1, B1, X1, 0, 200, 1e-12, 0.0);
271 PCG(*A2, M2, B2, X2, 0, 200, 1e-12, 0.0);
274 a_ar[0]->RecoverFEMSolution(X1, *b_ar[0], x1);
275 a_ar[1]->RecoverFEMSolution(X2, *b_ar[1], x2);
281 double dxmax = std::numeric_limits<float>::min();
282 double x1inf = x1.Normlinf();
284 for (
int i = 0; i < number_boundary_1; i++)
286 int idx = ess_tdof_list1_int[i];
287 double dx = std::abs(x1(idx)-interp_vals1(i))/x1inf;
288 if (dx > dxmax) { dxmax = dx; }
289 x1(idx) = interp_vals1(i);
292 for (
int i = 0; i < number_boundary_2; i++)
294 int idx = ess_tdof_list2_int[i];
295 double dx = std::abs(x2(idx)-interp_vals2(i))/x2inf;
296 if (dx > dxmax) { dxmax = dx; }
297 x2(idx) = interp_vals2(i);
303 std::cout << std::setprecision(8) <<
305 ", Relative residual: " << dxmax << endl;
306 if (dxmax < rel_tol) {
break; }
313 for (
int ip = 0; ip<mesharr.
Size(); ++ip)
316 sol_sock.precision(8);
317 sol_sock <<
"parallel " << mesharr.
Size() <<
" " << ip <<
"\n";
318 if (ip==0) { sol_sock <<
"solution\n" << *mesharr[ip] << x1 << flush; }
319 if (ip==1) { sol_sock <<
"solution\n" << *mesharr[ip] << x2 << flush; }
320 sol_sock <<
"window_title 'Overlapping grid solution'\n"
321 <<
"window_geometry "
322 << 0 <<
" " << 0 <<
" " << 450 <<
" " << 350 <<
"\n"
323 <<
"keys jmcA]]]" << endl;
330 for (
int i = 0; i < nmeshes; i++)
333 delete fespacearr[i];
334 if (order > 0) {
delete fecarr[i]; }
350 int number_boundary_1 = ess_tdof_list1.
Size(),
351 number_boundary_2 = ess_tdof_list2.
Size(),
352 number_true_1 = mesh_nodes_1.
Size()/
dim,
353 number_true_2 = mesh_nodes_2.
Size()/
dim;
355 Vector bnd1(number_boundary_1*dim);
356 for (
int i = 0; i < number_boundary_1; i++)
358 int idx = ess_tdof_list1[i];
359 for (
int d = 0; d <
dim; d++)
361 bnd1(i+d*number_boundary_1) = mesh_nodes_1(idx + d*number_true_1);
365 Vector bnd2(number_boundary_2*dim);
366 for (
int i = 0; i < number_boundary_2; i++)
368 int idx = ess_tdof_list2[i];
369 for (
int d = 0; d <
dim; d++)
371 bnd2(i+d*number_boundary_2) = mesh_nodes_2(idx + d*number_true_2);
382 for (
int i = 0; i < number_boundary_1; i++)
384 int idx = ess_tdof_list1[i];
385 if (code_out2[i] != 2) { ess_tdof_list1_int.
Append(idx); }
388 for (
int i = 0; i < number_boundary_2; i++)
390 int idx = ess_tdof_list2[i];
391 if (code_out1[i] != 2) { ess_tdof_list2_int.
Append(idx); }
virtual void Interpolate(const GridFunction &field_in, Vector &field_out)
int Size() const
Return the logical size of the array.
Class for domain integration L(v) := (f, v)
Class for grid function - Vector with associated FE space.
A coefficient that is constant across space and time.
void FindPoints(const Vector &point_pos, int point_pos_ordering=Ordering::byNODES)
Pointer to an Operator of a specified type.
int Size() const
Returns the size of the vector.
double Normlinf() const
Returns the l_infinity norm of the vector.
struct schwarz_common schwarz
Data type for Gauss-Seidel smoother of sparse matrix.
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
int Append(const T &el)
Append element 'el' to array, resize if necessary.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void Setup(Mesh &m, const double bb_t=0.1, const double newt_tol=1.0e-12, const int npt_max=256)
void PCG(const Operator &A, Solver &B, const Vector &b, Vector &x, int print_iter, int max_num_iter, double RTOLERANCE, double ATOLERANCE)
Preconditioned conjugate gradient method. (tolerances are squared)
void PrintUsage(std::ostream &out) const
Print the usage message.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
virtual const Array< unsigned int > & GetCode() const
void PrintOptions(std::ostream &out) const
Print the options.
FindPointsGSLIB can robustly evaluate a GridFunction on an arbitrary collection of points...
Arbitrary order H1-conforming (continuous) finite elements.
void GetInterdomainBoundaryPoints(FindPointsGSLIB &finder1, FindPointsGSLIB &finder2, Vector &mesh_nodes_1, Vector &mesh_nodes_2, Array< int > ess_tdof_list1, Array< int > ess_tdof_list2, Array< int > &ess_tdof_list1_int, Array< int > &ess_tdof_list2_int, const int dim)
bool Good() const
Return true if the command line options were parsed successfully.