xref: /petsc/src/binding/petsc4py/test/test_tao.py (revision 58ad77e8b9ee6fdbdfef97ebcff79a2d98620aab)
1# --------------------------------------------------------------------
2
3from math import sqrt
4from petsc4py import PETSc
5import unittest
6import numpy
7
8
9# --------------------------------------------------------------------
10class Objective:
11    def __call__(self, tao, x):
12        return (x[0] - 2.0) ** 2 + (x[1] - 2.0) ** 2 - 2.0 * (x[0] + x[1])
13
14
15class Gradient:
16    def __call__(self, tao, x, g):
17        g[0] = 2.0 * (x[0] - 2.0) - 2.0
18        g[1] = 2.0 * (x[1] - 2.0) - 2.0
19        g.assemble()
20
21
22class EqConstraints:
23    def __call__(self, tao, x, c):
24        c[0] = x[0] ** 2 + x[1] - 2.0
25        c.assemble()
26
27
28class EqJacobian:
29    def __call__(self, tao, x, J, P):
30        P[0, 0] = 2.0 * x[0]
31        P[0, 1] = 1.0
32        P.assemble()
33        if J != P:
34            J.assemble()
35
36
37class InEqConstraints:
38    def __call__(self, tao, x, c):
39        c[0] = x[1] - x[0] ** 2
40        c.assemble()
41
42
43class InEqJacobian:
44    def __call__(self, tao, x, J, P):
45        P[0, 0] = -2.0 * x[0]
46        P[0, 1] = 1.0
47        P.assemble()
48        if J != P:
49            J.assemble()
50
51
52class BaseTestTAO:
53    COMM = None
54
55    def setUp(self):
56        self.tao = PETSc.TAO().create(comm=self.COMM)
57
58    def tearDown(self):
59        self.tao = None
60        PETSc.garbage_cleanup()
61
62    def testSetRoutinesToNone(self):
63        tao = self.tao
64        objective, gradient, objgrad = None, None, None
65        constraint, varbounds = None, None
66        hessian, jacobian = None, None
67        tao.setObjective(objective)
68        tao.setGradient(gradient, None)
69        tao.setVariableBounds(varbounds)
70        tao.setObjectiveGradient(objgrad, None)
71        tao.setConstraints(constraint)
72        tao.setHessian(hessian)
73        tao.setJacobian(jacobian)
74
75    def testGetVecsAndMats(self):
76        tao = self.tao
77        x = tao.getSolution()
78        (g, _) = tao.getGradient()
79        low, up = tao.getVariableBounds()
80        r = None  # tao.getConstraintVec()
81        H, HP = None, None  # tao.getHessianMat()
82        J, JP = None, None  # tao.getJacobianMat()
83        for o in [
84            x,
85            g,
86            r,
87            low,
88            up,
89            H,
90            HP,
91            J,
92            JP,
93        ]:
94            self.assertFalse(o)
95
96    def testGetKSP(self):
97        ksp = self.tao.getKSP()
98        self.assertFalse(ksp)
99
100    def testEqualityConstraints(self):
101        if self.tao.getComm().Get_size() > 1:
102            return
103        tao = self.tao
104
105        x = PETSc.Vec().create(tao.getComm())
106        x.setType('standard')
107        x.setSizes(2)
108        c = PETSc.Vec().create(tao.getComm())
109        c.setSizes(1)
110        c.setType(x.getType())
111        J = PETSc.Mat().create(tao.getComm())
112        J.setSizes([1, 2])
113        J.setType(PETSc.Mat.Type.DENSE)
114        J.setUp()
115
116        tao.setObjective(Objective())
117        tao.setGradient(Gradient(), None)
118        tao.setEqualityConstraints(EqConstraints(), c)
119        tao.setJacobianEquality(EqJacobian(), J, J)
120        tao.setSolution(x)
121        tao.setType(PETSc.TAO.Type.ALMM)
122        tao.setALMMType(PETSc.TAO.ALMMType.PHR)
123        tao.setTolerances(gatol=1.0e-4)
124        tao.setFromOptions()
125        tao.solve()
126        self.assertTrue(tao.getALMMType() == PETSc.TAO.ALMMType.PHR)
127        self.assertAlmostEqual(abs(x[0] ** 2 + x[1] - 2.0), 0.0, places=4)
128        self.assertAlmostEqual(x[0], 0.7351392590499015014254200465, places=4)
129        self.assertAlmostEqual(x[1], 1.4595702698035618134357683666, places=4)
130
131    def testInequlityConstraints(self):
132        if self.tao.getComm().Get_size() > 1:
133            return
134        tao = self.tao
135
136        x = PETSc.Vec().create(tao.getComm())
137        x.setType('standard')
138        x.setSizes(2)
139        c = PETSc.Vec().create(tao.getComm())
140        c.setSizes(1)
141        c.setType(x.getType())
142        J = PETSc.Mat().create(tao.getComm())
143        J.setSizes([1, 2])
144        J.setType(PETSc.Mat.Type.DENSE)
145        J.setUp()
146
147        tao.setObjective(Objective())
148        tao.setGradient(Gradient(), None)
149        tao.setInequalityConstraints(InEqConstraints(), c)
150        tao.setJacobianInequality(InEqJacobian(), J, J)
151        tao.setSolution(x)
152        tao.setType(PETSc.TAO.Type.ALMM)
153        tao.setALMMType(PETSc.TAO.ALMMType.CLASSIC)
154        tao.setTolerances(gatol=1.0e-4)
155        tao.setFromOptions()
156        tao.solve()
157
158        self.assertTrue(tao.getALMMType() == PETSc.TAO.ALMMType.CLASSIC)
159        self.assertTrue(x[1] - x[0] ** 2 >= -1.0e-4)
160        self.assertAlmostEqual(x[0], 0.5 + sqrt(7) / 2, places=4)
161        self.assertAlmostEqual(x[1], 2 + sqrt(7) / 2, places=4)
162
163    def testBNCG(self):
164        if self.tao.getComm().Get_size() > 1:
165            return
166        tao = self.tao
167
168        x = PETSc.Vec().create(tao.getComm())
169        x.setType('standard')
170        x.setSizes(2)
171        xl = PETSc.Vec().create(tao.getComm())
172        xl.setType('standard')
173        xl.setSizes(2)
174        xl.set(0.0)
175        xu = PETSc.Vec().create(tao.getComm())
176        xu.setType('standard')
177        xu.setSizes(2)
178        xu.set(2.0)
179        tao.setVariableBounds((xl, xu))
180        tao.setObjective(Objective())
181        tao.setGradient(Gradient(), None)
182        tao.setSolution(x)
183        tao.setType(PETSc.TAO.Type.BNCG)
184        tao.setTolerances(gatol=1.0e-4)
185        ls = tao.getLineSearch()
186        ls.setType(PETSc.TAOLineSearch.Type.UNIT)
187        tao.setFromOptions()
188        tao.solve()
189        self.assertAlmostEqual(x[0], 2.0, places=4)
190        self.assertAlmostEqual(x[1], 2.0, places=4)
191
192    def testBQNLS(self):
193        if self.tao.getComm().Get_size() > 1:
194            return
195        tao = self.tao
196
197        x = PETSc.Vec().create(tao.getComm())
198        x.setType('standard')
199        x.setSizes(2)
200        xl = PETSc.Vec().create(tao.getComm())
201        xl.setType('standard')
202        xl.setSizes(2)
203        xl.set(0.0)
204        xu = PETSc.Vec().create(tao.getComm())
205        xu.setType('standard')
206        xu.setSizes(2)
207        xu.set(2.0)
208        tao.setVariableBounds((xl, xu))
209        tao.setObjective(Objective())
210        tao.setGradient(Gradient(), None)
211        tao.setSolution(x)
212        tao.setType(PETSc.TAO.Type.BQNLS)
213        tao.setTolerances(gatol=1.0e-4)
214        H = PETSc.Mat().createDense((2, 2), comm=tao.getComm())
215        H[0, 0] = 2
216        H[0, 1] = 0
217        H[1, 0] = 0
218        H[1, 1] = 2
219        H.assemble()
220        tao.getLMVMMat().setLMVMJ0(H)
221        tao.setFromOptions()
222        tao.solve()
223        self.assertEqual(tao.getIterationNumber(), 1)
224        self.assertAlmostEqual(x[0], 2.0, places=4)
225        self.assertAlmostEqual(x[1], 2.0, places=4)
226        self.assertTrue(tao.getLMVMMat().getLMVMJ0().equal(H))
227
228
229# --------------------------------------------------------------------
230
231
232class TestTAOSelf(BaseTestTAO, unittest.TestCase):
233    COMM = PETSc.COMM_SELF
234
235
236class TestTAOWorld(BaseTestTAO, unittest.TestCase):
237    COMM = PETSc.COMM_WORLD
238
239
240# --------------------------------------------------------------------
241
242
243if numpy.iscomplexobj(PETSc.ScalarType()):
244    del BaseTestTAO
245    del TestTAOSelf
246    del TestTAOWorld
247
248if __name__ == '__main__':
249    unittest.main()
250