-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathassignment20.py
executable file
·210 lines (139 loc) · 6.02 KB
/
assignment20.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/usr/bin/env python
import numpy as np
from PyTrilinos import Teuchos
from PyTrilinos import Epetra
from PyTrilinos import EpetraExt
from PyTrilinos import NOX
class OneDimNonliear(NOX.Epetra.Interface.Required):
def __init__(self, comm, nx=10, xmin=0.0, xmax=1.0, k=1.0):
super().__init__()
self.comm = comm
self.rank = comm.MyPID()
self.size = comm.NumProc()
self.xmin, self.xmax = xmin, xmax
self.nx = nx
self.dx = (xmax - xmin) / (nx - 1)
self.k = k
self.create_graph()
standard_map = self.get_standard_map()
self.has_boundary_condition_1 = (standard_map.MinMyGID() == standard_map.MinAllGID())
self.has_boundary_condition_2 = (standard_map.MaxMyGID() == standard_map.MaxAllGID())
self.create_slice()
self.boundary_condition_1 = 0.0
self.boundary_condition_2 = 1.0
self.create_vectors_and_importer()
def set_boundary_condition(self, side="left", value=0.0):
if side == "left":
self.boundary_condition_1 = value
if side == "right":
self.boundary_condition_2 = value
self.create_vectors_and_importer()
def create_slice(self):
standard_map = self.get_standard_map()
if self.has_boundary_condition_1:
s0 = 1
else:
s0 = None
if self.has_boundary_condition_2:
s1 = -1
else:
s1 = None
self.slice = slice(s0, s1)
def create_graph(self):
standard_map = Epetra.Map(self.nx, 0, self.comm)
self.graph = Epetra.CrsGraph(Epetra.Copy, standard_map, 3)
for gid in standard_map.MyGlobalElements():
# Boundaries: Dirichlet boundary conditions
if gid in (0, self.nx - 1):
self.graph.InsertGlobalIndices(gid, [gid])
else:
self.graph.InsertGlobalIndices(gid, [gid - 1, gid, gid + 1])
self.graph.FillComplete()
def create_vectors_and_importer(self):
self.u = Epetra.Vector(self.graph.RowMap(), True)
#Fill with initial guess (a straight line between boundary conditions)
self.u[:] = self.boundary_condition_1 + (self.get_standard_map().MyGlobalElements() *
(self.boundary_condition_2 - self.boundary_condition_1) / (self.nx - 1))
self.u_overlap = Epetra.Vector(self.get_overlap_map())
self.u_sorted_overlap = np.zeros_like(self.u_overlap[:], dtype=np.double)
self.sorted_overlap_indices = np.argsort(self.get_overlap_map().MyGlobalElements())
self.importer = Epetra.Import(self.get_overlap_map(), self.get_standard_map())
def computeF(self, u, F, flag):
"""
This is the function that NOX calls back to in order to compute F(u).
Arguments u and F are provided as Epetra.Vector objects, complete with
numpy interface.
"""
try:
# Initialization: get the overlap u, mesh size, and perform the
# communication
#####################
### Add code here ###
#####################
return True
except Exception as e:
print("Processor", self.rank,
"OneDimNonliear.computeF() has thrown an exception:")
print(str(type(e))[18:-2] + ":", e)
return False
def solve(self):
#Suppress 'Aztec status AZ_loss: loss of precision' messages
self.comm.SetTracebackMode(0)
#Get the initial solution vector
initial_guess = self.get_solution()
nox_initial_guess = NOX.Epetra.Vector(initial_guess, NOX.Epetra.Vector.CreateView)
# Define the ParameterLists
nonlinear_parameters = NOX.Epetra.defaultNonlinearParameters(self.comm, 2)
print_parameters = nonlinear_parameters["Printing"]
linear_solver_parameters = nonlinear_parameters["Linear Solver"]
# Define the Jacobian interface/operator
matrix_free_operator = NOX.Epetra.MatrixFree(print_parameters, self, nox_initial_guess)
# Define the Preconditioner interface/operator
preconditioner = NOX.Epetra.FiniteDifferenceColoring(print_parameters, self, initial_guess, self.get_graph(), True)
#Create and execute the solver
solver = NOX.Epetra.defaultSolver(initial_guess, self, matrix_free_operator, matrix_free_operator,
preconditioner, preconditioner, nonlinear_parameters)
solve_status = solver.solve()
if solve_status != NOX.StatusTest.Converged:
if self.rank == 0:
print("Nonlinear solver failed to converge")
def get_graph(self):
return self.graph
def get_standard_map(self):
return self.get_graph().RowMap()
def get_overlap_map(self):
return self.get_graph().ColMap()
def get_slice(self):
return self.slice
def get_solution(self):
return self.u
def get_overlap_solution(self):
return self.u_overlap
def get_sorted_overlap_solution(self):
return self.u_sorted_overlap
def get_importer(self):
return self.importer
def get_sorted_overlap_indices(self):
return self.sorted_overlap_indices
def get_final_solution(self):
balanced_map = self.u.Map()
if self.rank == 0:
my_global_elements = balanced_map.NumGlobalElements()
else:
my_global_elements = 0
temp_map = Epetra.Map(-1, my_global_elements, 0, self.comm)
solution = Epetra.Vector(temp_map)
importer = Epetra.Import(temp_map, balanced_map)
solution.Import(self.u, importer, Epetra.Insert)
return solution.ExtractCopy()
if __name__ == '__main__':
import matplotlib.pyplot as plt
comm = Epetra.PyComm()
solver = OneDimNonliear(comm, nx=10, k=10)
solver.solve()
sol = solver.get_final_solution()
print(sol)
if comm.MyPID() == 0:
x = np.linspace(solver.xmin, solver.xmax, num=solver.nx)
plt.plot(x, sol[:])
plt.savefig('test.png')