105. Iteration methods in parallel#
from ipyparallel import Cluster
c = await Cluster(engines="mpi").start_and_connect(n=4, activate=True)
c.ids
Starting 4 engines with <class 'ipyparallel.cluster.launcher.MPIEngineSetLauncher'>
[0, 1, 2, 3]
%%px
from mpi4py import MPI
comm = MPI.COMM_WORLD
from ngsolve import *
comm = MPI.COMM_WORLD
mesh = Mesh(unit_square.GenerateMesh(maxh=0.1, comm=comm))
setup a standard problem, in parallel. We use a Jacobi preconditioner: it extracts local diagonals, and cumulates them over identified dofs.
%%px
fes = H1(mesh, dirichlet='.*')
u,v = fes.TnT()
a = BilinearForm(grad(u)*grad(v)*dx).Assemble()
f = LinearForm(1*v*dx).Assemble()
gfu = GridFunction(fes)
pre = Preconditioner(a, "local") # Jacobi preconditioner
pre.Update()
105.1. Richardson iteration#
The right hand side vector f.vec is distributed, the vector gfu.vec of the gridfunction is consistent. Create help vectors of the same type:
residual calculation
r = f - A uis purely localthe preconditioning step
w = pre * rincludes type conversion from a distributed input to a consistent outputthe inner product for the error acts on two vectors of opposite type
solution vector update can be done purely local
%%px
r = f.vec.CreateVector() # a distributed vector
w = gfu.vec.CreateVector() # a consistent vector
for it in range(100):
r.data = f.vec - a.mat * gfu.vec
w.data = pre * r
err = InnerProduct(w, r)
if comm.rank==0: print (err)
gfu.vec.data += w
[stdout:0] 0.0021064513366757624
0.0016649942356400777
0.0014293622352480324
0.0012540554438783874
0.001112404612257642
0.0009933390479475918
0.000890831942976833
0.0008011690168185088
0.0007218924281157399
0.0006512848690148516
0.0005880862634490914
0.0005313295098339835
0.00048024242401788295
0.0004341879116486988
0.0003926266502992656
0.0003550932023919776
0.00032118024145896124
0.00029052774906968394
0.0002628153108169191
0.00023775638776913217
0.00021509388242576453
0.0001945965815081428
0.00017605621543874845
0.00015928496924243752
0.00014411333724077553
0.0001303882493063521
0.00011797141848740605
0.00010673787378974326
9.657465096663952e-05
8.737962020820057e-05
7.906043377785088e-05
7.153357960521118e-05
6.472352903316176e-05
5.856196859246741e-05
5.298710700251122e-05
4.794304967465525e-05
4.33792338922704e-05
3.924991860282375e-05
3.551372341262978e-05
3.2133211945081825e-05
2.9074515223568345e-05
2.630699118224849e-05
2.380291680011571e-05
2.15372097032181e-05
1.9487176392098893e-05
1.7632284531086348e-05
1.595395698683949e-05
1.4435385528847577e-05
1.3061362307207032e-05
1.1818127405416772e-05
1.0693230930278576e-05
9.675408249165827e-06
8.754467118573381e-06
7.921185568486566e-06
7.1672195160009044e-06
6.485019179969889e-06
5.867753457298018e-06
5.309241501770909e-06
4.803890818858559e-06
4.346641255507124e-06
3.9329143232140194e-06
3.5585673462821717e-06
3.2198519756196523e-06
2.913376652277429e-06
2.636072644562713e-06
2.38516331841581e-06
2.1581363331689332e-06
1.9527184841408617e-06
1.7668529400544409e-06
1.5986786472714488e-06
1.4465116945531416e-06
1.3088284517023017e-06
1.1842503132148085e-06
1.071529894150113e-06
9.695385399768453e-07
8.77255025312514e-07
7.937553283851727e-07
7.182033788183627e-07
6.498426860896932e-07
5.879887648335622e-07
5.320222811376854e-07
4.813828512053036e-07
4.355634302857997e-07
3.9410523568941653e-07
3.565931530484706e-07
3.226515798276342e-07
2.9194066446357063e-07
2.641529034764591e-07
2.390100624797615e-07
2.1626039025863877e-07
1.9567609802136595e-07
1.7705107858376246e-07
1.6019884264875789e-07
1.4495065151739598e-07
1.3115382753416282e-07
1.1867022534926646e-07
1.073748486908884e-07
9.715459879719703e-08
8.79071419763558e-08
7.953988495554161e-08
from ngsolve.webgui import Draw
gfu = c[:]['gfu']
Draw(gfu[0]);
Very similar for other iteraton methods, such as Conjugate Gradients. The matrix operation goes from consistent to distributed without communication, the preconditioner does the cumulation. The inner products are between different vector types:
%%px
from ngsolve.krylovspace import CGSolver
inv = CGSolver(a.mat, pre, printrates=comm.rank==0)
gfu.vec.data = inv * f.vec
[stdout:0] CG iteration 1, residual = 0.0458960928258143
CG iteration 2, residual = 0.07023551604308398
CG iteration 3, residual = 0.050613080017471855
CG iteration 4, residual = 0.036110304721396196
CG iteration 5, residual = 0.024371225619145134
CG iteration 6, residual = 0.012037144772437378
CG iteration 7, residual = 0.003957451163626997
CG iteration 8, residual = 0.002808522019112092
CG iteration 9, residual = 0.0019576676071666097
CG iteration 10, residual = 0.0012105518357746058
CG iteration 11, residual = 0.0006678458492479842
CG iteration 12, residual = 0.00034994343416230693
CG iteration 13, residual = 0.00015505713813410548
CG iteration 14, residual = 9.053904926414744e-05
CG iteration 15, residual = 4.1301684511661955e-05
CG iteration 16, residual = 2.681164276691173e-05
CG iteration 17, residual = 1.3058747054232963e-05
CG iteration 18, residual = 4.920983843351047e-06
CG iteration 19, residual = 1.8602999450351314e-06
CG iteration 20, residual = 1.0070126786667637e-06
CG iteration 21, residual = 5.936469705558383e-07
CG iteration 22, residual = 4.061853379897207e-07
CG iteration 23, residual = 3.073398845261929e-07
CG iteration 24, residual = 1.2811327744940765e-07
CG iteration 25, residual = 7.645607659519623e-08
CG iteration 26, residual = 3.576003073963308e-08
CG iteration 27, residual = 1.3675779003025412e-08
CG iteration 28, residual = 5.429352347662427e-09
CG iteration 29, residual = 2.7388776138098953e-09
CG iteration 30, residual = 1.492972650904689e-09
CG iteration 31, residual = 6.559774367270432e-10
CG iteration 32, residual = 2.2925027188366396e-10
CG iteration 33, residual = 9.769065823884045e-11
CG iteration 34, residual = 3.873546483208607e-11
CG iteration 35, residual = 1.087987525169979e-11
CG iteration 36, residual = 3.638827062697718e-12
CG iteration 37, residual = 1.0472900892991234e-12
CG iteration 38, residual = 2.905348173962424e-13
CG iteration 39, residual = 7.585404739032898e-14
CG iteration 40, residual = 2.59351193019184e-14
gfu = c[:]['gfu']
Draw(gfu[0]);
c.shutdown(hub=True)