ngsolve 6.2.2506.post74.dev0__cp314-cp314-macosx_10_15_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ngsolve might be problematic. Click here for more details.

Files changed (315) hide show
  1. netgen/include/analytic_integrals.hpp +10 -0
  2. netgen/include/arnoldi.hpp +55 -0
  3. netgen/include/bandmatrix.hpp +334 -0
  4. netgen/include/basematrix.hpp +957 -0
  5. netgen/include/basevector.hpp +1268 -0
  6. netgen/include/bdbequations.hpp +2805 -0
  7. netgen/include/bdbintegrator.hpp +1660 -0
  8. netgen/include/bem_diffops.hpp +475 -0
  9. netgen/include/bessel.hpp +1064 -0
  10. netgen/include/bilinearform.hpp +963 -0
  11. netgen/include/bla.hpp +29 -0
  12. netgen/include/blockalloc.hpp +95 -0
  13. netgen/include/blockjacobi.hpp +328 -0
  14. netgen/include/bspline.hpp +116 -0
  15. netgen/include/calcinverse.hpp +141 -0
  16. netgen/include/cg.hpp +368 -0
  17. netgen/include/chebyshev.hpp +44 -0
  18. netgen/include/cholesky.hpp +720 -0
  19. netgen/include/clapack.h +7254 -0
  20. netgen/include/code_generation.hpp +296 -0
  21. netgen/include/coefficient.hpp +2033 -0
  22. netgen/include/coefficient_impl.hpp +19 -0
  23. netgen/include/coefficient_stdmath.hpp +167 -0
  24. netgen/include/commutingAMG.hpp +106 -0
  25. netgen/include/comp.hpp +79 -0
  26. netgen/include/compatibility.hpp +41 -0
  27. netgen/include/complex_wrapper.hpp +73 -0
  28. netgen/include/compressedfespace.hpp +110 -0
  29. netgen/include/contact.hpp +235 -0
  30. netgen/include/diagonalmatrix.hpp +154 -0
  31. netgen/include/differentialoperator.hpp +276 -0
  32. netgen/include/diffop.hpp +1286 -0
  33. netgen/include/diffop_impl.hpp +328 -0
  34. netgen/include/diffopwithfactor.hpp +123 -0
  35. netgen/include/discontinuous.hpp +84 -0
  36. netgen/include/dump.hpp +949 -0
  37. netgen/include/ectypes.hpp +121 -0
  38. netgen/include/eigen.hpp +60 -0
  39. netgen/include/eigensystem.hpp +18 -0
  40. netgen/include/elasticity_equations.hpp +595 -0
  41. netgen/include/elementbyelement.hpp +195 -0
  42. netgen/include/elementtopology.hpp +1760 -0
  43. netgen/include/elementtransformation.hpp +339 -0
  44. netgen/include/evalfunc.hpp +405 -0
  45. netgen/include/expr.hpp +1686 -0
  46. netgen/include/facetfe.hpp +175 -0
  47. netgen/include/facetfespace.hpp +180 -0
  48. netgen/include/facethofe.hpp +111 -0
  49. netgen/include/facetsurffespace.hpp +112 -0
  50. netgen/include/fe_interfaces.hpp +32 -0
  51. netgen/include/fem.hpp +87 -0
  52. netgen/include/fesconvert.hpp +14 -0
  53. netgen/include/fespace.hpp +1449 -0
  54. netgen/include/finiteelement.hpp +286 -0
  55. netgen/include/globalinterfacespace.hpp +77 -0
  56. netgen/include/globalspace.hpp +115 -0
  57. netgen/include/gridfunction.hpp +525 -0
  58. netgen/include/h1amg.hpp +124 -0
  59. netgen/include/h1hofe.hpp +188 -0
  60. netgen/include/h1hofe_impl.hpp +1262 -0
  61. netgen/include/h1hofefo.hpp +148 -0
  62. netgen/include/h1hofefo_impl.hpp +185 -0
  63. netgen/include/h1hofespace.hpp +167 -0
  64. netgen/include/h1lofe.hpp +1240 -0
  65. netgen/include/h1lumping.hpp +41 -0
  66. netgen/include/hcurl_equations.hpp +1381 -0
  67. netgen/include/hcurlcurlfe.hpp +2241 -0
  68. netgen/include/hcurlcurlfespace.hpp +78 -0
  69. netgen/include/hcurlfe.hpp +259 -0
  70. netgen/include/hcurlfe_utils.hpp +107 -0
  71. netgen/include/hcurlhdiv_dshape.hpp +857 -0
  72. netgen/include/hcurlhdivfes.hpp +308 -0
  73. netgen/include/hcurlhofe.hpp +175 -0
  74. netgen/include/hcurlhofe_impl.hpp +1871 -0
  75. netgen/include/hcurlhofespace.hpp +193 -0
  76. netgen/include/hcurllofe.hpp +1146 -0
  77. netgen/include/hdiv_equations.hpp +880 -0
  78. netgen/include/hdivdivfe.hpp +2923 -0
  79. netgen/include/hdivdivsurfacespace.hpp +76 -0
  80. netgen/include/hdivfe.hpp +206 -0
  81. netgen/include/hdivfe_utils.hpp +717 -0
  82. netgen/include/hdivfes.hpp +75 -0
  83. netgen/include/hdivhofe.hpp +447 -0
  84. netgen/include/hdivhofe_impl.hpp +1107 -0
  85. netgen/include/hdivhofefo.hpp +229 -0
  86. netgen/include/hdivhofespace.hpp +177 -0
  87. netgen/include/hdivhosurfacefespace.hpp +106 -0
  88. netgen/include/hdivlofe.hpp +773 -0
  89. netgen/include/hidden.hpp +74 -0
  90. netgen/include/householder.hpp +181 -0
  91. netgen/include/hypre_ams_precond.hpp +123 -0
  92. netgen/include/hypre_precond.hpp +73 -0
  93. netgen/include/integrator.hpp +2012 -0
  94. netgen/include/integratorcf.hpp +253 -0
  95. netgen/include/interpolate.hpp +49 -0
  96. netgen/include/intrule.hpp +2542 -0
  97. netgen/include/intrules_SauterSchwab.hpp +25 -0
  98. netgen/include/irspace.hpp +49 -0
  99. netgen/include/jacobi.hpp +153 -0
  100. netgen/include/kernels.hpp +762 -0
  101. netgen/include/l2hofe.hpp +194 -0
  102. netgen/include/l2hofe_impl.hpp +564 -0
  103. netgen/include/l2hofefo.hpp +542 -0
  104. netgen/include/l2hofespace.hpp +344 -0
  105. netgen/include/la.hpp +38 -0
  106. netgen/include/linearform.hpp +266 -0
  107. netgen/include/matrix.hpp +2140 -0
  108. netgen/include/memusage.hpp +41 -0
  109. netgen/include/meshaccess.hpp +1359 -0
  110. netgen/include/mgpre.hpp +204 -0
  111. netgen/include/mp_coefficient.hpp +145 -0
  112. netgen/include/mptools.hpp +2281 -0
  113. netgen/include/multigrid.hpp +42 -0
  114. netgen/include/multivector.hpp +447 -0
  115. netgen/include/mumpsinverse.hpp +187 -0
  116. netgen/include/mycomplex.hpp +361 -0
  117. netgen/include/ng_lapack.hpp +1661 -0
  118. netgen/include/ngblas.hpp +1232 -0
  119. netgen/include/ngs_defines.hpp +30 -0
  120. netgen/include/ngs_stdcpp_include.hpp +106 -0
  121. netgen/include/ngs_utils.hpp +121 -0
  122. netgen/include/ngsobject.hpp +1019 -0
  123. netgen/include/ngsstream.hpp +113 -0
  124. netgen/include/ngstd.hpp +72 -0
  125. netgen/include/nodalhofe.hpp +96 -0
  126. netgen/include/nodalhofe_impl.hpp +141 -0
  127. netgen/include/normalfacetfe.hpp +223 -0
  128. netgen/include/normalfacetfespace.hpp +98 -0
  129. netgen/include/normalfacetsurfacefespace.hpp +84 -0
  130. netgen/include/order.hpp +251 -0
  131. netgen/include/parallel_matrices.hpp +222 -0
  132. netgen/include/paralleldofs.hpp +340 -0
  133. netgen/include/parallelngs.hpp +23 -0
  134. netgen/include/parallelvector.hpp +269 -0
  135. netgen/include/pardisoinverse.hpp +200 -0
  136. netgen/include/periodic.hpp +129 -0
  137. netgen/include/plateaufespace.hpp +25 -0
  138. netgen/include/pml.hpp +275 -0
  139. netgen/include/pmltrafo.hpp +631 -0
  140. netgen/include/postproc.hpp +142 -0
  141. netgen/include/potentialtools.hpp +22 -0
  142. netgen/include/precomp.hpp +60 -0
  143. netgen/include/preconditioner.hpp +602 -0
  144. netgen/include/prolongation.hpp +377 -0
  145. netgen/include/python_comp.hpp +107 -0
  146. netgen/include/python_fem.hpp +89 -0
  147. netgen/include/python_linalg.hpp +58 -0
  148. netgen/include/python_ngstd.hpp +386 -0
  149. netgen/include/recursive_pol.hpp +4896 -0
  150. netgen/include/recursive_pol_tet.hpp +395 -0
  151. netgen/include/recursive_pol_trig.hpp +492 -0
  152. netgen/include/reorderedfespace.hpp +81 -0
  153. netgen/include/sample_sort.hpp +105 -0
  154. netgen/include/scalarfe.hpp +335 -0
  155. netgen/include/shapefunction_utils.hpp +113 -0
  156. netgen/include/simd_complex.hpp +329 -0
  157. netgen/include/smoother.hpp +253 -0
  158. netgen/include/solve.hpp +89 -0
  159. netgen/include/sparsecholesky.hpp +313 -0
  160. netgen/include/sparsematrix.hpp +1038 -0
  161. netgen/include/sparsematrix_dyn.hpp +90 -0
  162. netgen/include/sparsematrix_impl.hpp +1013 -0
  163. netgen/include/special_matrix.hpp +463 -0
  164. netgen/include/specialelement.hpp +125 -0
  165. netgen/include/statushandler.hpp +33 -0
  166. netgen/include/stringops.hpp +12 -0
  167. netgen/include/superluinverse.hpp +136 -0
  168. netgen/include/symbolicintegrator.hpp +850 -0
  169. netgen/include/symmetricmatrix.hpp +144 -0
  170. netgen/include/tangentialfacetfe.hpp +224 -0
  171. netgen/include/tangentialfacetfespace.hpp +91 -0
  172. netgen/include/tensor.hpp +522 -0
  173. netgen/include/tensorcoefficient.hpp +446 -0
  174. netgen/include/tensorproductintegrator.hpp +113 -0
  175. netgen/include/thcurlfe.hpp +128 -0
  176. netgen/include/thcurlfe_impl.hpp +380 -0
  177. netgen/include/thdivfe.hpp +80 -0
  178. netgen/include/thdivfe_impl.hpp +492 -0
  179. netgen/include/tpdiffop.hpp +461 -0
  180. netgen/include/tpfes.hpp +133 -0
  181. netgen/include/tpintrule.hpp +224 -0
  182. netgen/include/triangular.hpp +465 -0
  183. netgen/include/tscalarfe.hpp +245 -0
  184. netgen/include/tscalarfe_impl.hpp +1029 -0
  185. netgen/include/umfpackinverse.hpp +148 -0
  186. netgen/include/vector.hpp +1273 -0
  187. netgen/include/voxelcoefficientfunction.hpp +41 -0
  188. netgen/include/vtkoutput.hpp +198 -0
  189. netgen/include/vvector.hpp +208 -0
  190. netgen/include/webgui.hpp +92 -0
  191. netgen/libngbla.dylib +0 -0
  192. netgen/libngcomp.dylib +0 -0
  193. netgen/libngfem.dylib +0 -0
  194. netgen/libngla.dylib +0 -0
  195. netgen/libngsbem.dylib +0 -0
  196. netgen/libngsolve.dylib +0 -0
  197. netgen/libngstd.dylib +0 -0
  198. ngsolve/TensorProductTools.py +210 -0
  199. ngsolve/__console.py +94 -0
  200. ngsolve/__expr.py +181 -0
  201. ngsolve/__init__.py +148 -0
  202. ngsolve/__init__.pyi +233 -0
  203. ngsolve/_scikit_build_core_dependencies.py +30 -0
  204. ngsolve/bla.pyi +1153 -0
  205. ngsolve/bvp.py +78 -0
  206. ngsolve/bvp.pyi +32 -0
  207. ngsolve/cmake/NGSolveConfig.cmake +102 -0
  208. ngsolve/cmake/ngsolve-targets-release.cmake +79 -0
  209. ngsolve/cmake/ngsolve-targets.cmake +163 -0
  210. ngsolve/comp/__init__.pyi +5449 -0
  211. ngsolve/comp/pml.pyi +89 -0
  212. ngsolve/config/__init__.py +1 -0
  213. ngsolve/config/__init__.pyi +43 -0
  214. ngsolve/config/__main__.py +4 -0
  215. ngsolve/config/config.py +60 -0
  216. ngsolve/config/config.pyi +45 -0
  217. ngsolve/demos/TensorProduct/__init__.py +0 -0
  218. ngsolve/demos/TensorProduct/tp_dg_1d_1d.py +80 -0
  219. ngsolve/demos/TensorProduct/tp_dg_1d_2d.py +73 -0
  220. ngsolve/demos/TensorProduct/tp_dg_2d_1d.py +72 -0
  221. ngsolve/demos/TensorProduct/tp_dg_2d_2d.py +66 -0
  222. ngsolve/demos/__init__.py +0 -0
  223. ngsolve/demos/howto/__init__.py +0 -0
  224. ngsolve/demos/howto/hhj.py +44 -0
  225. ngsolve/demos/howto/hybrid_dg.py +53 -0
  226. ngsolve/demos/howto/mixed.py +30 -0
  227. ngsolve/demos/howto/nonlin.py +29 -0
  228. ngsolve/demos/howto/pickling.py +26 -0
  229. ngsolve/demos/howto/pml.py +31 -0
  230. ngsolve/demos/howto/taskmanager.py +20 -0
  231. ngsolve/demos/howto/tdnns.py +47 -0
  232. ngsolve/demos/howto/timeDG-skeleton.py +45 -0
  233. ngsolve/demos/howto/timeDG.py +38 -0
  234. ngsolve/demos/howto/timeDGlap.py +42 -0
  235. ngsolve/demos/howto/timeDGwave.py +61 -0
  236. ngsolve/demos/intro/__init__.py +0 -0
  237. ngsolve/demos/intro/adaptive.py +123 -0
  238. ngsolve/demos/intro/cmagnet.py +59 -0
  239. ngsolve/demos/intro/elasticity.py +76 -0
  240. ngsolve/demos/intro/navierstokes.py +74 -0
  241. ngsolve/demos/intro/poisson.ipynb +170 -0
  242. ngsolve/demos/intro/poisson.py +41 -0
  243. ngsolve/demos/mpi/__init__.py +0 -0
  244. ngsolve/demos/mpi/mpi_cmagnet.py +87 -0
  245. ngsolve/demos/mpi/mpi_navierstokes.py +117 -0
  246. ngsolve/demos/mpi/mpi_poisson.py +89 -0
  247. ngsolve/demos/mpi/mpi_timeDG.py +82 -0
  248. ngsolve/directsolvers.py +26 -0
  249. ngsolve/directsolvers.pyi +15 -0
  250. ngsolve/eigenvalues.py +364 -0
  251. ngsolve/eigenvalues.pyi +30 -0
  252. ngsolve/fem.pyi +1647 -0
  253. ngsolve/internal.py +89 -0
  254. ngsolve/krylovspace.py +1013 -0
  255. ngsolve/krylovspace.pyi +298 -0
  256. ngsolve/la.pyi +1230 -0
  257. ngsolve/meshes.py +748 -0
  258. ngsolve/ngs2petsc.py +310 -0
  259. ngsolve/ngscxx.py +42 -0
  260. ngsolve/ngslib.so +0 -0
  261. ngsolve/ngstd.pyi +59 -0
  262. ngsolve/nonlinearsolvers.py +203 -0
  263. ngsolve/nonlinearsolvers.pyi +95 -0
  264. ngsolve/preconditioners.py +11 -0
  265. ngsolve/preconditioners.pyi +7 -0
  266. ngsolve/solve.pyi +109 -0
  267. ngsolve/solve_implementation.py +168 -0
  268. ngsolve/solve_implementation.pyi +42 -0
  269. ngsolve/solvers.py +7 -0
  270. ngsolve/solvers.pyi +14 -0
  271. ngsolve/timestepping.py +185 -0
  272. ngsolve/timestepping.pyi +28 -0
  273. ngsolve/timing.py +108 -0
  274. ngsolve/timing.pyi +54 -0
  275. ngsolve/utils.py +167 -0
  276. ngsolve/utils.pyi +273 -0
  277. ngsolve/webgui.py +670 -0
  278. ngsolve-6.2.2506.post74.dev0.data/data/Netgen.icns +0 -0
  279. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngscxx +17 -0
  280. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngsld +13 -0
  281. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngsolve.tcl +648 -0
  282. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngspy +2 -0
  283. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/beam.geo +17 -0
  284. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/beam.vol +240 -0
  285. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/chip.in2d +41 -0
  286. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/chip.vol +614 -0
  287. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coil.geo +12 -0
  288. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coil.vol +2560 -0
  289. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coilshield.geo +24 -0
  290. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coilshield.vol +3179 -0
  291. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/cube.geo +19 -0
  292. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/cube.vol +1832 -0
  293. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d10_DGdoubleglazing.pde +50 -0
  294. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d11_chip_nitsche.pde +40 -0
  295. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d1_square.pde +43 -0
  296. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d2_chip.pde +35 -0
  297. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d3_helmholtz.pde +22 -0
  298. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d4_cube.pde +46 -0
  299. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d5_beam.pde +74 -0
  300. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d6_shaft.pde +73 -0
  301. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d7_coil.pde +50 -0
  302. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d8_coilshield.pde +49 -0
  303. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d9_hybridDG.pde +72 -0
  304. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/doubleglazing.in2d +27 -0
  305. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/doubleglazing.vol +737 -0
  306. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/piezo2d40round4.vol.gz +0 -0
  307. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/shaft.geo +73 -0
  308. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/shaft.vol +4291 -0
  309. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/square.in2d +17 -0
  310. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/square.vol +149 -0
  311. ngsolve-6.2.2506.post74.dev0.dist-info/METADATA +13 -0
  312. ngsolve-6.2.2506.post74.dev0.dist-info/RECORD +315 -0
  313. ngsolve-6.2.2506.post74.dev0.dist-info/WHEEL +5 -0
  314. ngsolve-6.2.2506.post74.dev0.dist-info/licenses/LICENSE +504 -0
  315. ngsolve-6.2.2506.post74.dev0.dist-info/top_level.txt +2 -0
ngsolve/krylovspace.py ADDED
@@ -0,0 +1,1013 @@
1
+
2
+ from ngsolve import Projector, Norm, TimeFunction, BaseMatrix, Preconditioner, InnerProduct, \
3
+ Norm, sqrt, Vector, Matrix, BaseVector, BlockVector, BitArray
4
+ from typing import Optional, Callable, Union
5
+ import logging
6
+ from netgen.libngpy._meshing import _PushStatus, _GetStatus, _SetThreadPercentage
7
+ from math import log
8
+ import os
9
+
10
+
11
+ if os.name == "nt":
12
+ _clear_line_command = ""
13
+ else:
14
+ _clear_line_command = "\33[2K"
15
+
16
+ linear_solver_param_doc = """
17
+ mat : BaseMatrix
18
+ The left hand side of the equation to solve.
19
+
20
+ pre : Preconditioner, BaseMatrix = None
21
+ If provided, the preconditioner for the system.
22
+
23
+ freedofs : BitArray = None
24
+ If no preconditioner is provided, the BitArray of the FESpace freedofs must be given.
25
+
26
+ tol : double = 1e-12
27
+ Relative tolerance for the residuum reduction.
28
+
29
+ maxiter : int = 100
30
+ Maximum number of iterations, if reached solver will emit a warning.
31
+
32
+ callback : Callable[[int, float], None] = None
33
+ Callback function that is called with iteration number and residual in each iteration step.
34
+
35
+ callback_sol : Callable[[BaseVector], None] = None
36
+ Callback function that is called with solution x_k in each iteration step.
37
+
38
+ printrates : bool = False
39
+ Print iterations to stdout. One can give a string to be passed as an `end`
40
+ argument to the print function, for example:
41
+ >>> printrates="\r"
42
+ will call
43
+ >>> print("iteration = 1, residual = 1e-3", end="\r")
44
+ if "\r" is passed, a final output will also be printed.
45
+
46
+ plotrates : bool = False
47
+ matplotlib plot of errors (residuals)
48
+ """
49
+
50
+ class LinearSolver(BaseMatrix):
51
+ """Base class for linear solvers.
52
+ """ + linear_solver_param_doc
53
+ name = "LinearSolver"
54
+ def __init__(self, mat : BaseMatrix,
55
+ pre : Optional[Preconditioner] = None,
56
+ freedofs : Optional[BitArray] = None,
57
+ tol : float = None,
58
+ maxiter : int = 100,
59
+ atol : float = None,
60
+ callback : Optional[Callable[[int, float], None]] = None,
61
+ callback_sol : Optional[Callable[[BaseVector], None]] = None,
62
+ printrates : bool = False,
63
+ plotrates : bool = False):
64
+ super().__init__()
65
+ if atol is None and tol is None:
66
+ tol = 1e-12
67
+ self.mat = mat
68
+ assert (freedofs is None) != (pre is None) # either pre or freedofs must be given
69
+ self.pre = pre if pre else Projector(freedofs, True)
70
+ self.tol = tol
71
+ self.atol = atol
72
+ self.maxiter = maxiter
73
+ self.callback = callback
74
+ self.callback_sol = callback_sol
75
+ self.printrates = printrates
76
+ self.plotrates = plotrates
77
+ self.residuals = []
78
+ self.iterations = 0
79
+
80
+ @TimeFunction
81
+ def Solve(self, rhs : BaseVector, sol : Optional[BaseVector] = None,
82
+ initialize : bool = True) -> BaseVector:
83
+ self.iterations = 0
84
+ self.residuals = []
85
+ old_status = _GetStatus()
86
+ _PushStatus(self.name + " Solve")
87
+ _SetThreadPercentage(0)
88
+ if sol is None:
89
+ sol = rhs.CreateVector()
90
+ initialize = True
91
+ if initialize:
92
+ sol[:] = 0
93
+ self.sol = sol
94
+ self._SolveImpl(rhs=rhs, sol=sol)
95
+ if old_status[0] != "idle":
96
+ _PushStatus(old_status[0])
97
+ _SetThreadPercentage(old_status[1])
98
+ return sol
99
+
100
+ def Height(self) -> int:
101
+ return self.mat.width
102
+
103
+ def Width(self) -> int:
104
+ return self.mat.height
105
+
106
+ def CreateVector(self,col):
107
+ return self.mat.CreateVector(not col)
108
+
109
+ def IsComplex(self) -> bool:
110
+ return self.mat.IsComplex()
111
+
112
+ def Mult(self, x : BaseVector, y : BaseVector) -> None:
113
+ self.Solve(rhs=x, sol=y, initialize=True)
114
+
115
+ def Update(self):
116
+ if hasattr(self.pre, "Update"):
117
+ self.pre.Update()
118
+
119
+ def CheckResidual(self, residual):
120
+ self.iterations += 1
121
+ self.residuals.append(residual)
122
+ if len(self.residuals) == 1:
123
+ if self.tol is None:
124
+ self._final_residual = self.atol
125
+ else:
126
+ self._final_residual = residual * self.tol
127
+ if self.atol is not None:
128
+ self._final_residual = max(self._final_residual, self.atol)
129
+ else:
130
+ if self.callback is not None:
131
+ self.callback(self.iterations, residual)
132
+ if self.callback_sol is not None:
133
+ self.callback_sol(self.sol)
134
+ if self.residuals[0] != 0:
135
+ logerrstop = log(self._final_residual)
136
+ logerrfirst = log(self.residuals[0])
137
+ if residual == 0:
138
+ _SetThreadPercentage(100)
139
+ else:
140
+ _SetThreadPercentage(100.*max(self.iterations/self.maxiter,
141
+ (log(residual)-logerrfirst)/(logerrstop - logerrfirst)))
142
+ if self.printrates:
143
+ print("{}{} iteration {}, residual = {} ".format(_clear_line_command, self.name, self.iterations, residual), end="\n" if isinstance(self.printrates, bool) else self.printrates)
144
+ if self.iterations == self.maxiter and residual > self._final_residual:
145
+ print("{}WARNING: {} did not converge to TOL".format(_clear_line_command, self.name))
146
+ is_converged = self.iterations >= self.maxiter or residual <= self._final_residual
147
+ if is_converged and self.printrates == "\r":
148
+ print("{}{} {}converged in {} iterations to residual {}".format(_clear_line_command, self.name, "NOT " if residual >= self._final_residual else "", self.iterations, residual))
149
+
150
+ if self.plotrates:
151
+ if self.iterations==1:
152
+ import matplotlib.pyplot as plt
153
+ from IPython.display import display, clear_output
154
+ fig, ax = plt.subplots()
155
+ self.plt = plt
156
+ self.ax = ax
157
+ self.fig = fig
158
+ self.its = []
159
+ self.ress = []
160
+ self.clear_output=clear_output
161
+ self.display=display
162
+ plt.ioff()
163
+ plt.show()
164
+ self.its.append(self.iterations)
165
+ self.ress.append(residual)
166
+ # update_plot(plt, ax, self.its, self.ress)
167
+ self.ax.clear()
168
+ self.ax.semilogy(self.its, self.ress, label='error')
169
+ self.ax.set_xlabel('iteration')
170
+ self.ax.set_ylabel('error')
171
+ self.ax.set_title('CG Solver Convergence')
172
+ self.ax.legend()
173
+ self.plt.draw()
174
+ self.clear_output(wait=True)
175
+ self.display(self.fig)
176
+
177
+
178
+ return is_converged
179
+
180
+ class CGSolver(LinearSolver):
181
+ """Preconditioned conjugate gradient method
182
+
183
+ Parameters
184
+ ----------
185
+
186
+ """ + linear_solver_param_doc + """
187
+
188
+ conjugate : bool = False
189
+ If set to True, then the complex inner product is used, else a pseudo inner product that makes CG work with complex symmetric matrices.
190
+ """
191
+ name = "CG"
192
+
193
+ def __init__(self, *args,
194
+ conjugate : bool = False,
195
+ abstol : float = None,
196
+ maxsteps : int = None,
197
+ printing : bool = False,
198
+ **kwargs):
199
+ if printing:
200
+ print("WARNING: printing is deprecated, use printrates instead!")
201
+ kwargs["printrates"] = printing
202
+ if abstol is not None:
203
+ print("WARNING: abstol is deprecated, use atol instead!")
204
+ kwargs["abstol"] = abstol
205
+ if maxsteps is not None:
206
+ print("WARNING: maxsteps is deprecated, use maxiter instead!")
207
+ kwargs["maxiter"] = maxsteps
208
+ super().__init__(*args, **kwargs)
209
+ self.conjugate = conjugate
210
+
211
+ # for backward compatibility
212
+ @property
213
+ def errors(self):
214
+ return self.residuals
215
+
216
+ def _SolveImpl(self, rhs : BaseVector, sol : BaseVector):
217
+ d, w, s = [sol.CreateVector() for i in range(3)]
218
+ conjugate = self.conjugate
219
+ d.data = rhs - self.mat * sol
220
+ w.data = self.pre * d
221
+ s.data = w
222
+ wdn = w.InnerProduct(d, conjugate=conjugate)
223
+ if self.CheckResidual(sqrt(abs(wdn))):
224
+ return
225
+
226
+ while True:
227
+ w.data = self.mat * s
228
+ wd = wdn
229
+ as_s = s.InnerProduct(w, conjugate=conjugate)
230
+ if as_s == 0 or wd == 0: break
231
+ alpha = wd / as_s
232
+ sol.data += alpha * s
233
+ d.data += (-alpha) * w
234
+
235
+ w.data = self.pre * d
236
+
237
+ wdn = w.InnerProduct(d, conjugate=conjugate)
238
+ if self.CheckResidual(sqrt(abs(wdn))):
239
+ return
240
+
241
+ beta = wdn / wd
242
+ s *= beta
243
+ s.data += w
244
+
245
+
246
+ def CG(mat, rhs, pre=None, sol=None, tol=1e-12, maxsteps = 100, printrates = True, plotrates = False, initialize = True, conjugate=False, callback=None, **kwargs):
247
+ """preconditioned conjugate gradient method
248
+
249
+
250
+ Parameters
251
+ ----------
252
+
253
+ mat : Matrix
254
+ The left hand side of the equation to solve. The matrix has to be spd o hermitsch.
255
+
256
+ rhs : Vector
257
+ The right hand side of the equation.
258
+
259
+ pre : Preconditioner
260
+ If provided the preconditioner is used.
261
+
262
+ sol : Vector
263
+ Start vector for CG method, if initialize is set False. Gets overwritten by the solution vector. If sol = None then a new vector is created.
264
+
265
+ tol : double
266
+ Tolerance of the residuum. CG stops if tolerance is reached.
267
+
268
+ maxsteps : int
269
+ Number of maximal steps for CG. If the maximal number is reached before the tolerance is reached CG stops.
270
+
271
+ printrates : bool
272
+ If set to True then the error of the iterations is displayed.
273
+
274
+ plotrates : bool
275
+ If set to True then the error of the iterations is plotted.
276
+
277
+ initialize : bool
278
+ If set to True then the initial guess for the CG method is set to zero. Otherwise the values of the vector sol, if provided, is used.
279
+
280
+ conjugate : bool
281
+ If set to True, then the complex inner product is used.
282
+
283
+
284
+ Returns
285
+ -------
286
+ (vector)
287
+ Solution vector of the CG method.
288
+
289
+ """
290
+ solver = CGSolver(mat=mat, pre=pre, conjugate=conjugate, tol=tol, maxiter=maxsteps,
291
+ callback=callback, printrates=printrates, plotrates=plotrates, **kwargs)
292
+ solver.Solve(rhs=rhs, sol=sol, initialize=initialize)
293
+ return solver.sol
294
+
295
+ class QMRSolver(LinearSolver):
296
+ """Quasi Minimal Residuum method
297
+
298
+ Parameters
299
+ ----------
300
+
301
+ """ + linear_solver_param_doc + """
302
+
303
+ pre2 : Preconditioner = None
304
+ Second preconditioner, if provided.
305
+
306
+ ep : double
307
+ Start epsilon.
308
+ """
309
+
310
+ name = "QMR"
311
+
312
+ def __init__(self, *args, pre2 : Preconditioner = None,
313
+ ep : float = 1., **kwargs):
314
+ super().__init__(*args, **kwargs)
315
+ self.pre2 = pre2
316
+ self.ep = ep
317
+
318
+ def _SolveImpl(self, rhs : BaseVector, sol : BaseVector):
319
+ u, mat, ep, pre1, pre2 = sol, self.mat, self.ep, self.pre, self.pre2
320
+ r = rhs.CreateVector()
321
+ v = rhs.CreateVector()
322
+ v_tld = rhs.CreateVector()
323
+ w = rhs.CreateVector()
324
+ w_tld = rhs.CreateVector()
325
+ y = rhs.CreateVector()
326
+ y_tld = rhs.CreateVector()
327
+ z = rhs.CreateVector()
328
+ z_tld = rhs.CreateVector()
329
+ p = rhs.CreateVector()
330
+ p_tld = rhs.CreateVector()
331
+ q = rhs.CreateVector()
332
+ d = rhs.CreateVector()
333
+ s = rhs.CreateVector()
334
+
335
+ r.data = rhs - mat * u
336
+ v_tld.data = r
337
+ y.data = pre1 * v_tld
338
+
339
+ rho = InnerProduct(y,y)
340
+ rho = sqrt(rho)
341
+
342
+ w_tld.data = r
343
+ z.data = pre2.T * w_tld if pre2 else w_tld
344
+
345
+ xi = InnerProduct(z,z)
346
+ xi = sqrt(xi)
347
+
348
+ gamma = 1.0
349
+ eta = -1.0
350
+ theta = 0.0
351
+
352
+ for i in range(1,self.maxiter+1):
353
+ if (rho == 0.0):
354
+ print('Breakdown in rho')
355
+ return
356
+ if (xi == 0.0):
357
+ print('Breakdown in xi')
358
+ return
359
+ v.data = (1.0/rho) * v_tld
360
+ y.data = (1.0/rho) * y
361
+
362
+ w.data = (1.0/xi) * w_tld
363
+ z.data = (1.0/xi) * z
364
+
365
+ delta = InnerProduct(z,y)
366
+ if (delta == 0.0):
367
+ print('Breakdown in delta')
368
+ return
369
+
370
+ y_tld.data = pre2 * y if pre2 else y
371
+ z_tld.data = pre1.T * z
372
+
373
+ if (i > 1):
374
+ p.data = (-xi*delta / ep) * p
375
+ p.data += y_tld
376
+
377
+ q.data = (-rho * delta / ep) * q
378
+ q.data += z_tld
379
+ else:
380
+ p.data = y_tld
381
+ q.data = z_tld
382
+
383
+ p_tld.data = mat * p
384
+ ep = InnerProduct(q, p_tld)
385
+ if (ep == 0.0):
386
+ print('Breakdown in epsilon')
387
+ return
388
+
389
+ beta = ep/delta
390
+ if (beta == 0.0):
391
+ print('Breakdown in beta')
392
+ return
393
+
394
+ v_tld.data = p_tld - beta * v;
395
+
396
+ y.data = pre1 * v_tld
397
+
398
+ rho_1 = rho
399
+ rho = InnerProduct(y,y)
400
+ rho = sqrt(rho)
401
+
402
+ w_tld.data = mat.T * q
403
+ w_tld.data -= beta * w
404
+
405
+ z.data = pre2.T * w_tld if pre2 else w_tld
406
+
407
+ xi = InnerProduct(z,z)
408
+ xi = sqrt(xi)
409
+
410
+ gamma_1 = gamma
411
+ theta_1 = theta
412
+
413
+ theta = rho/(gamma_1 * abs(beta))
414
+ gamma = 1.0 / sqrt(1.0 + theta * theta)
415
+ if (gamma == 0.0):
416
+ print('Breakdown in gamma')
417
+ return
418
+
419
+ eta = -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1);
420
+
421
+ if (i > 1):
422
+ d.data = (theta_1 * theta_1 * gamma * gamma) * d
423
+ d.data += eta * p
424
+
425
+ s.data = (theta_1 * theta_1 * gamma * gamma) * s
426
+ s.data += eta * p_tld
427
+
428
+ else:
429
+ d.data = eta * p
430
+ s.data = eta * p_tld
431
+
432
+ u.data += d
433
+ r.data -= s
434
+
435
+ #Projected residuum: Better terminating condition necessary?
436
+ v.data = self.pre * r
437
+ ResNorm = sqrt(InnerProduct(r,v))
438
+ # ResNorm = sqrt( np.dot(r.FV().NumPy()[fdofs],r.FV().NumPy()[fdofs]))
439
+ #ResNorm = sqrt(InnerProduct(r,r))
440
+ if self.CheckResidual(ResNorm):
441
+ return
442
+
443
+ def QMR(mat, rhs, fdofs, pre1=None, pre2=None, sol=None, maxsteps = 100, printrates = True, initialize = True, ep = 1.0, tol = 1e-7):
444
+ """Quasi Minimal Residuum method
445
+
446
+
447
+ Parameters
448
+ ----------
449
+
450
+ mat : Matrix
451
+ The left hand side of the equation to solve
452
+
453
+ rhs : Vector
454
+ The right hand side of the equation.
455
+
456
+ fdofs : BitArray
457
+ BitArray of free degrees of freedoms.
458
+
459
+ pre1 : Preconditioner
460
+ First preconditioner if provided
461
+
462
+ pre2 : Preconditioner
463
+ Second preconditioner if provided
464
+
465
+ sol : Vector
466
+ Start vector for QMR method, if initialize is set False. Gets overwritten by the solution vector. If sol = None then a new vector is created.
467
+
468
+ maxsteps : int
469
+ Number of maximal steps for QMR. If the maximal number is reached before the tolerance is reached QMR stops.
470
+
471
+ printrates : bool
472
+ If set to True then the error of the iterations is displayed.
473
+
474
+ initialize : bool
475
+ If set to True then the initial guess for the QMR method is set to zero. Otherwise the values of the vector sol, if provided, is used.
476
+
477
+ ep : double
478
+ Start epsilon.
479
+
480
+ tol : double
481
+ Tolerance of the residuum. QMR stops if tolerance is reached.
482
+
483
+
484
+ Returns
485
+ -------
486
+ (vector)
487
+ Solution vector of the QMR method.
488
+
489
+ """
490
+ # backwards compatibility, but freedofs are not needed then.
491
+ if pre1 is not None:
492
+ fdofs = None
493
+ return QMRSolver(mat=mat, freedofs=fdofs, pre=pre1,
494
+ pre2=pre2, maxiter=maxsteps,
495
+ printrates=printrates, ep=ep,
496
+ tol=tol).Solve(rhs=rhs, sol=sol, initialize=initialize)
497
+
498
+
499
+
500
+
501
+ #Source: Michael Kolmbauer https://www.numa.uni-linz.ac.at/Teaching/PhD/Finished/kolmbauer-diss.pdf
502
+ class MinResSolver(LinearSolver):
503
+ """Minimal Residuum method
504
+
505
+ Parameters
506
+ ----------
507
+ """ + linear_solver_param_doc
508
+ def __init__(self, *args, **kwargs):
509
+ super().__init__(*args, **kwargs)
510
+
511
+ def _SolveImpl(self, rhs: BaseVector, sol : BaseVector):
512
+ pre, mat, u = self.pre, self.mat, sol
513
+ v_new = rhs.CreateVector()
514
+ v = rhs.CreateVector()
515
+ v_old = rhs.CreateVector()
516
+ w_new = rhs.CreateVector()
517
+ w = rhs.CreateVector()
518
+ w_old = rhs.CreateVector()
519
+ z_new = rhs.CreateVector()
520
+ z = rhs.CreateVector()
521
+ mz = rhs.CreateVector()
522
+
523
+ v.data = rhs - mat * u
524
+
525
+ z.data = pre * v
526
+
527
+ #First Step
528
+ gamma = sqrt(InnerProduct(z,v))
529
+ gamma_new = 0
530
+ z.data = 1/gamma * z
531
+ v.data = 1/gamma * v
532
+
533
+ ResNorm = gamma
534
+ ResNorm_old = gamma
535
+
536
+ if self.CheckResidual(ResNorm):
537
+ return
538
+
539
+ eta_old = gamma
540
+ c_old = 1
541
+ c = 1
542
+ s_new = 0
543
+ s = 0
544
+ s_old = 0
545
+
546
+ v_old[:] = 0.0
547
+ w_old[:] = 0.0
548
+ w[:] = 0.0
549
+
550
+ k = 1
551
+ while True:
552
+ mz.data = mat*z
553
+ delta = InnerProduct(mz,z)
554
+ v_new.data = mz - delta*v - gamma * v_old
555
+
556
+ z_new.data = pre * v_new
557
+
558
+ gamma_new = sqrt(InnerProduct(z_new, v_new))
559
+ z_new *= 1/gamma_new
560
+ v_new *= 1/gamma_new
561
+
562
+ alpha0 = c*delta - c_old*s*gamma
563
+ alpha1 = sqrt(alpha0*alpha0 + gamma_new*gamma_new) #**
564
+ alpha2 = s*delta + c_old*c*gamma
565
+ alpha3 = s_old * gamma
566
+
567
+ c_new = alpha0/alpha1
568
+ s_new = gamma_new/alpha1
569
+
570
+ w_new.data = z - alpha3*w_old - alpha2*w
571
+ w_new.data = 1/alpha1 * w_new
572
+
573
+ u.data += c_new*eta_old * w_new
574
+ eta = -s_new * eta_old
575
+
576
+ #update of residuum
577
+ ResNorm = abs(s_new) * ResNorm_old
578
+ if self.CheckResidual(ResNorm):
579
+ return
580
+ k += 1
581
+
582
+ # shift vectors by renaming
583
+ v_old, v, v_new = v, v_new, v_old
584
+ w_old, w, w_new = w, w_new, w_old
585
+ z, z_new = z_new, z
586
+
587
+ eta_old = eta
588
+
589
+ s_old = s
590
+ s = s_new
591
+
592
+ c_old = c
593
+ c = c_new
594
+
595
+ gamma = gamma_new
596
+ ResNorm_old = ResNorm
597
+
598
+ def MinRes(mat, rhs, pre=None, sol=None, maxsteps = 100, printrates = True, initialize = True, tol = 1e-7):
599
+ """Minimal Residuum method
600
+
601
+
602
+ Parameters
603
+ ----------
604
+
605
+ mat : Matrix
606
+ The left hand side of the equation to solve
607
+
608
+ rhs : Vector
609
+ The right hand side of the equation.
610
+
611
+ pre : Preconditioner
612
+ If provided the preconditioner is used.
613
+
614
+ sol : Vector
615
+ Start vector for MinRes method, if initialize is set False. Gets overwritten by the solution vector. If sol = None then a new vector is created.
616
+
617
+ maxsteps : int
618
+ Number of maximal steps for MinRes. If the maximal number is reached before the tolerance is reached MinRes stops.
619
+
620
+ printrates : bool
621
+ If set to True then the error of the iterations is displayed.
622
+
623
+ initialize : bool
624
+ If set to True then the initial guess for the MinRes method is set to zero. Otherwise the values of the vector sol, if prevented, is used.
625
+
626
+ tol : double
627
+ Tolerance of the residuum. MinRes stops if tolerance is reached.
628
+
629
+
630
+ Returns
631
+ -------
632
+ (vector)
633
+ Solution vector of the MinRes method.
634
+
635
+ """
636
+ return MinResSolver(mat=mat, pre=pre, maxiter=maxsteps,
637
+ printrates=printrates,
638
+ tol=tol).Solve(rhs=rhs, sol=sol,
639
+ initialize=initialize)
640
+
641
+
642
+ class RichardsonSolver(LinearSolver):
643
+ """ Preconditioned Richardson Iteration
644
+
645
+ Parameters
646
+ ----------
647
+ """ + linear_solver_param_doc + """
648
+
649
+ dampfactor : float = 1.
650
+ Set the damping factor for the Richardson iteration. If it is 1 then no damping is done. Values greater than 1 are allowed.
651
+ """
652
+ name = "Richardson"
653
+ def __init__(self, *args, dampfactor = 1., **kwargs):
654
+ super().__init__(*args, **kwargs)
655
+ self.dampfactor = dampfactor
656
+
657
+ def _SolveImpl(self, rhs : BaseVector, sol : BaseVector):
658
+ r = rhs.CreateVector()
659
+ d = sol.CreateVector()
660
+ r.data = rhs - self.mat*sol
661
+ d.data = self.pre * r
662
+ res_norm = abs(InnerProduct(d,r))
663
+ if self.CheckResidual(res_norm):
664
+ return
665
+
666
+ while True:
667
+ sol.data += self.dampfactor * d
668
+ r.data = rhs - self.mat * sol
669
+ d.data = self.pre * r
670
+
671
+ res_norm = abs(InnerProduct(d,r))
672
+ if self.CheckResidual(res_norm):
673
+ return
674
+
675
+
676
+ def PreconditionedRichardson(a, rhs, pre=None, freedofs=None, maxit=100, tol=1e-8, dampfactor=1.0, printing=True):
677
+ """ Preconditioned Richardson Iteration
678
+
679
+ Parameters
680
+ ----------
681
+ a : BilinearForm
682
+ The left hand side of the equation to solve
683
+
684
+ rhs : Vector
685
+ The right hand side of the equation.
686
+
687
+ pre : Preconditioner
688
+ If provided the preconditioner is used.
689
+
690
+ freedofs : BitArray
691
+ The FreeDofs on which the Richardson iteration acts. If argument is 'None' then the FreeDofs of the underlying FESpace is used.
692
+
693
+ maxit : int
694
+ Number of maximal iteration for Richardson iteration. If the maximal number is reached before the tolerance is reached a warning is displayed.
695
+
696
+ tol : double
697
+ Tolerance of the residuum. Richardson iteration stops if residuum < tolerance*initial_residuum is reached.
698
+
699
+ dampfactor : float
700
+ Set the damping factor for the Richardson iteration. If it is 1 then no damping is done. Values greater than 1 are allowed.
701
+
702
+ printing : bool
703
+ Set if Richardson iteration should print informations about the actual iteration like the residuum.
704
+
705
+ Returns
706
+ -------
707
+ (vector)
708
+ Solution vector of the Preconditioned Richardson iteration.
709
+
710
+ """
711
+ u = rhs.CreateVector()
712
+ r = rhs.CreateVector()
713
+ u[:] = 0
714
+
715
+ projector = Projector(freedofs if freedofs else a.space.FreeDofs(coupling=a.condense), False)
716
+
717
+ r.data = rhs # r.data = rhs - a.mat*u
718
+ r.data -= projector*r
719
+
720
+ it = 0
721
+ initial_res_norm = Norm(r)
722
+ if printing:
723
+ print("it =", it, " ||res||_2 =", initial_res_norm)
724
+
725
+ for it in range(1, maxit+1):
726
+ u.data += dampfactor*(pre*r if pre else r)
727
+ r.data = rhs - a.mat*u
728
+ r.data -= projector*r
729
+
730
+ res_norm = Norm(r)
731
+ if printing:
732
+ print("it =", it, " ||res||_2 =", res_norm)
733
+ if res_norm < tol*initial_res_norm:
734
+ break
735
+ else:
736
+ print("Warning: Preconditioned Richardson did not converge to TOL")
737
+
738
+ return u
739
+
740
+ class GMResSolver(LinearSolver):
741
+ """Preconditioned GMRes solver. Minimizes the preconditioned residuum pre * (b-A*x)
742
+
743
+ Parameters
744
+ ----------
745
+
746
+ """ + linear_solver_param_doc + """
747
+
748
+ innerproduct : Callable[[BaseVector, BaseVector], Union[float, complex]] = None
749
+ Innerproduct to be used in iteration, all orthogonalizations/norms are computed with respect to that inner product.
750
+
751
+ restart : int = None
752
+ If given, GMRes is restarted with the current solution x every 'restart' steps.
753
+ """
754
+ name = "GMRes"
755
+
756
+ def __init__(self, *args,
757
+ innerproduct : Optional[Callable[[BaseVector, BaseVector],
758
+ Union[float, complex]]] = None,
759
+ restart : Optional[int] = None,
760
+ **kwargs):
761
+ super().__init__(*args, **kwargs)
762
+ if innerproduct is not None:
763
+ self.innerproduct = innerproduct
764
+ self.norm = lambda x: sqrt(innerproduct(x,x).real)
765
+ self.restart = restart
766
+ else:
767
+ self.innerproduct = lambda x, y: y.InnerProduct(x, conjugate=True)
768
+ self.norm = Norm
769
+ self.restart = restart
770
+
771
+ def _SolveImpl(self, rhs : BaseVector, sol : BaseVector):
772
+ is_complex = rhs.is_complex
773
+ A, pre, innerproduct, norm = self.mat, self.pre, self.innerproduct, self.norm
774
+ n = len(rhs)
775
+ m = self.maxiter
776
+ sn = Vector(m, is_complex)
777
+ cs = Vector(m, is_complex)
778
+ sn[:] = 0
779
+ cs[:] = 0
780
+ if self.callback_sol is not None:
781
+ sol_start = sol.CreateVector()
782
+ sol_start.data = sol
783
+ r = rhs.CreateVector()
784
+ tmp = rhs.CreateVector()
785
+ tmp.data = rhs - A * sol
786
+ r.data = pre * tmp
787
+ Q = []
788
+ H = []
789
+ Q.append(rhs.CreateVector())
790
+ r_norm = norm(r)
791
+ if self.CheckResidual(abs(r_norm)):
792
+ return sol
793
+ Q[0].data = 1./r_norm * r
794
+ beta = Vector(m+1, is_complex)
795
+ beta[:] = 0
796
+ beta[0] = r_norm
797
+
798
+ def arnoldi(A,Q,k):
799
+ q = rhs.CreateVector()
800
+ tmp.data = A * Q[k]
801
+ q.data = pre * tmp
802
+ h = Vector(m+1, is_complex)
803
+ h[:] = 0
804
+ for i in range(k+1):
805
+ h[i] = innerproduct(Q[i],q)
806
+ q.data += (-1)* h[i] * Q[i]
807
+ h[k+1] = norm(q)
808
+ if abs(h[k+1]) < 1e-12:
809
+ return h, None
810
+ q *= 1./h[k+1].real
811
+ return h, q
812
+
813
+ def givens_rotation(v1,v2):
814
+ if v2 == 0:
815
+ return 1,0
816
+ elif v1 == 0:
817
+ return 0,v2/abs(v2)
818
+ else:
819
+ t = sqrt((v1.conjugate()*v1+v2.conjugate()*v2).real)
820
+ cs = abs(v1)/t
821
+ sn = v1/abs(v1) * v2.conjugate()/t
822
+ return cs,sn
823
+
824
+ def apply_givens_rotation(h, cs, sn, k):
825
+ for i in range(k):
826
+ temp = cs[i] * h[i] + sn[i] * h[i+1]
827
+ h[i+1] = -sn[i].conjugate() * h[i] + cs[i].conjugate() * h[i+1]
828
+ h[i] = temp
829
+ cs[k], sn[k] = givens_rotation(h[k], h[k+1])
830
+ h[k] = cs[k] * h[k] + sn[k] * h[k+1]
831
+ h[k+1] = 0
832
+
833
+ def calcSolution(k):
834
+ # if callback_sol is set we need to recompute solution in every step
835
+ if self.callback_sol is not None:
836
+ sol.data = sol_start
837
+ mat = Matrix(k+1,k+1, is_complex)
838
+ for i in range(k+1):
839
+ mat[:,i] = H[i][:k+1]
840
+ rs = Vector(k+1, is_complex)
841
+ rs[:] = beta[:k+1]
842
+ y = mat.I * rs
843
+ for i in range(k+1):
844
+ sol.data += y[i] * Q[i]
845
+
846
+ for k in range(m):
847
+ h,q = arnoldi(A,Q,k)
848
+ H.append(h)
849
+ if q is None:
850
+ break
851
+ Q.append(q)
852
+ apply_givens_rotation(h, cs, sn, k)
853
+ beta[k+1] = -sn[k].conjugate() * beta[k]
854
+ beta[k] = cs[k] * beta[k]
855
+ error = abs(beta[k+1])
856
+ if self.callback_sol is not None:
857
+ calcSolution(k)
858
+ if self.CheckResidual(error):
859
+ break
860
+ if self.restart is not None and (k+1 == self.restart and not (self.restart == self.maxiter)):
861
+ calcSolution(k)
862
+ del Q
863
+ restarted_solver = GMResSolver(mat=self.mat,
864
+ pre=self.pre,
865
+ tol=0,
866
+ atol=self._final_residual,
867
+ callback=self.callback,
868
+ callback_sol=self.callback_sol,
869
+ maxiter=self.maxiter,
870
+ restart=self.restart,
871
+ printrates=self.printrates)
872
+ restarted_solver.iterations = self.iterations
873
+ sol = restarted_solver.Solve(rhs = rhs, sol = sol, initialize=False)
874
+ self.residuals += restarted_solver.residuals
875
+ self.iterations = restarted_solver.iterations
876
+ return sol
877
+ calcSolution(k)
878
+ return sol
879
+
880
+ def GMRes(A, b, pre=None, freedofs=None, x=None, maxsteps = 100, tol = None, innerproduct=None,
881
+ callback=None, restart=None, startiteration=0, printrates=True, reltol=None):
882
+ """Restarting preconditioned gmres solver for A*x=b. Minimizes the preconditioned residuum pre*(b-A*x).
883
+
884
+ Parameters
885
+ ----------
886
+
887
+ A : BaseMatrix
888
+ The left hand side of the linear system.
889
+
890
+ b : BaseVector
891
+ The right hand side of the linear system.
892
+
893
+ pre : BaseMatrix = None
894
+ The preconditioner for the system. If no preconditioner is given, the freedofs
895
+ of the system must be given.
896
+
897
+ freedofs : BitArray = None
898
+ Freedofs to solve on, only necessary if no preconditioner is given.
899
+
900
+ x : BaseVector = None
901
+ Startvector, if given it will be modified in the routine and returned. Will be created
902
+ if not given.
903
+
904
+ maxsteps : int = 100
905
+ Maximum iteration steps.
906
+
907
+ tol : float = 1e-7
908
+
909
+ innerproduct : function = None
910
+ Innerproduct to be used in iteration, all orthogonalizations/norms are computed with
911
+ respect to that inner product.
912
+
913
+ callback : function = None
914
+ If given, this function is called with the solution vector x in each step. Only for debugging
915
+
916
+ restart : int = None
917
+ If given, gmres is restarted with the current solution x every 'restart' steps.
918
+
919
+ startiteration : int = 0
920
+ Internal value to count total number of iterations in restarted setup, no user input required
921
+ here.
922
+
923
+ printrates : bool = True
924
+ Print norm of preconditioned residual in each step.
925
+ """
926
+ solver = GMResSolver(mat=A, pre=pre, freedofs=freedofs,
927
+ maxiter=maxsteps, tol=reltol, atol=tol,
928
+ innerproduct=innerproduct,
929
+ callback_sol=callback, restart=restart,
930
+ printrates=printrates)
931
+ return solver.Solve(rhs=b, sol=x)
932
+
933
+
934
+
935
+
936
+ from ngsolve.la import EigenValues_Preconditioner
937
+ def BramblePasciakCG(A, B, C, f, g, preA, preS, maxit=1000, tol=1e-8, \
938
+ printrates=False):
939
+
940
+ printeol = "\n"
941
+ if isinstance(printrates, str):
942
+ printeol = printrates
943
+ printrates = True
944
+
945
+ lam = EigenValues_Preconditioner(A,preA)
946
+ if printrates==True:
947
+ print ("lammin/lammax = ", lam[0], '/', lam[-1])
948
+ preA = 1.2/lam[0]*preA # scaling
949
+
950
+
951
+ x = BlockVector([f.CreateVector(), g.CreateVector()])
952
+ w,r,p,ap = [x.CreateVector() for i in range(4)]
953
+
954
+ # r.data = b
955
+ # p.data = pre*r
956
+ pru = (preA * f).Evaluate()
957
+ r[0].data = A*pru - f
958
+ r[1].data = B*pru - g
959
+ p[0].data = pru
960
+ p[1].data = preS*r[1]
961
+
962
+ wrn = InnerProduct(r,p)
963
+ err0 = sqrt(wrn)
964
+
965
+ x[:] = 0
966
+ for it in range(maxit):
967
+ # ap.data = A * p
968
+ hv = (A * p[0] + B.T * p[1]).Evaluate()
969
+ papu = (preA * hv).Evaluate()
970
+ ap[0].data = A * papu - hv
971
+ ap[1].data = B * (papu - p[0])
972
+ if C is not None:
973
+ ap[1].data += C * p[1]
974
+
975
+ pap = InnerProduct(p, ap)
976
+ wr = wrn
977
+ alpha = wr / pap
978
+
979
+ x += alpha * p
980
+ r -= alpha * ap
981
+ pru -= alpha * papu
982
+
983
+ # w.data = pre*r
984
+ w[0].data = pru
985
+ w[1].data = preS * r[1]
986
+
987
+ wrn = InnerProduct(w, r)
988
+ err = sqrt(wrn)
989
+ if printrates==True:
990
+ print ("Iteration",it,"err=",err," ",end=printeol)
991
+ if err < tol * err0: break
992
+
993
+ beta = wrn / wr
994
+
995
+ p *= beta
996
+ p.data += w
997
+
998
+ return x[0], x[1]
999
+
1000
+
1001
+
1002
+ def update_plot(plt, ax, its, ress):
1003
+ # its.append(it)
1004
+ # ress.append(res)
1005
+ ax.clear()
1006
+ ax.semilogy(its, ress, label='error')
1007
+ ax.set_xlabel('iteration')
1008
+ ax.set_ylabel('error')
1009
+ ax.set_title('CG Solver Convergence')
1010
+ ax.legend()
1011
+ plt.draw()
1012
+ clear_output(wait=True)
1013
+ display(fig)