COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
atest-ufem-navier-stokes-taylor-green.py
Go to the documentation of this file.
1 import sys
2 import coolfluid as cf
3 import numpy as np
4 import os
5 from optparse import OptionParser
6 
7 env = cf.Core.environment()
8 
9 # Global configuration
10 env.assertion_throws = False
11 env.assertion_backtrace = False
12 env.exception_backtrace = False
13 env.regist_signal_handlers = False
14 env.log_level = 4
15 
17  Ua = 0.
18  Va = 0.
19  D = 0.5
20 
21  t = np.array([])
22  max_error = np.array([])
23 
24  model = None
25  solver = None
26  mesh = None
27 
28 
29  def __init__(self, dt, element):
30  self.dt = dt
31  self.element = element
32 
33  def __del__(self):
34  if self.model != None:
35  self.model.delete_component()
36 
37  def create_mesh(self, segments):
38  domain = self.model.Domain
39  blocks = domain.create_component('blocks', 'cf3.mesh.BlockMesh.BlockArrays')
40  points = blocks.create_points(dimensions = 2, nb_points = 6)
41  points[0] = [-0.5, -0.5]
42  points[1] = [0.5, -0.5]
43  points[2] = [-0.5, 0.]
44  points[3] = [0.5, 0.]
45  points[4] = [-0.5,0.5]
46  points[5] = [0.5, 0.5]
47 
48  block_nodes = blocks.create_blocks(2)
49  block_nodes[0] = [0, 1, 3, 2]
50  block_nodes[1] = [2, 3, 5, 4]
51 
52  block_subdivs = blocks.create_block_subdivisions()
53  block_subdivs[0] = [segments, segments/2]
54  block_subdivs[1] = [segments, segments/2]
55 
56  gradings = blocks.create_block_gradings()
57  gradings[0] = [1., 1., 1., 1.]
58  gradings[1] = [1., 1., 1., 1.]
59 
60  left_patch = blocks.create_patch_nb_faces(name = 'left', nb_faces = 2)
61  left_patch[0] = [2, 0]
62  left_patch[1] = [4, 2]
63 
64  bottom_patch = blocks.create_patch_nb_faces(name = 'bottom', nb_faces = 1)
65  bottom_patch[0] = [0, 1]
66 
67  top_patch = blocks.create_patch_nb_faces(name = 'top', nb_faces = 1)
68  top_patch[0] = [5, 4]
69 
70  right_patch = blocks.create_patch_nb_faces(name = 'right', nb_faces = 2)
71  right_patch[0] = [1, 3]
72  right_patch[1] = [3, 5]
73 
74  blocks.partition_blocks(nb_partitions = cf.Core.nb_procs(), direction = 0)
75 
76  mesh = domain.create_component('Mesh', 'cf3.mesh.Mesh')
77  self.mesh = mesh
78 
79  blocks.create_mesh(mesh.uri())
80 
81  create_point_region = domain.create_component('CreatePointRegion', 'cf3.mesh.actions.AddPointRegion')
82  create_point_region.coordinates = [0., 0.]
83  create_point_region.region_name = 'center'
84  create_point_region.mesh = mesh
85  create_point_region.execute()
86 
87  if self.element == 'triag':
88  triangulator = domain.create_component('Triangulator', 'cf3.mesh.MeshTriangulator')
89  triangulator.mesh = mesh
90  triangulator.execute()
91 
92 # partitioner = domain.create_component('Partitioner', 'cf3.mesh.actions.PeriodicMeshPartitioner')
93 # partitioner.mesh = mesh
94 
95 # link_horizontal = partitioner.create_link_periodic_nodes()
96 # link_horizontal.source_region = mesh.topology.right
97 # link_horizontal.destination_region = mesh.topology.left
98 # link_horizontal.translation_vector = [-1., 0.]
99 
100 # link_vertical = partitioner.create_link_periodic_nodes()
101 # link_vertical.source_region = mesh.topology.top
102 # link_vertical.destination_region = mesh.topology.bottom
103 # link_vertical.translation_vector = [0., -1.]
104 
105 # partitioner.execute()
106 
107  make_boundary_global = domain.create_component('MakeBoundaryGlobal', 'cf3.mesh.actions.MakeBoundaryGlobal')
108  make_boundary_global.mesh = mesh
109  make_boundary_global.execute()
110 
111  link_horizontal = domain.create_component('LinkHorizontal', 'cf3.mesh.actions.LinkPeriodicNodes')
112  link_horizontal.mesh = mesh
113  link_horizontal.source_region = mesh.topology.right
114  link_horizontal.destination_region = mesh.topology.left
115  link_horizontal.translation_vector = [-1., 0.]
116  link_horizontal.execute()
117 
118  link_vertical = domain.create_component('LinkVertical', 'cf3.mesh.actions.LinkPeriodicNodes')
119  link_vertical.mesh = mesh
120  link_vertical.source_region = mesh.topology.top
121  link_vertical.destination_region = mesh.topology.bottom
122  link_vertical.translation_vector = [0., -1.]
123  link_vertical.execute()
124 
125  partitioner = domain.create_component('Partitioner', 'cf3.zoltan.PHG')
126  partitioner.mesh = mesh
127  partitioner.execute()
128 
129  coords = self.mesh.geometry.coordinates
130  self.sample_coords = range(len(coords))
131  self.probe_points = []
132 
133  for i in range(len(coords)):
134  (x,y) = coords[i]
135  if x == (segments/4) * 1./float(segments) and y == 0.:
136  self.probe_points.append(i)
137  #
138  # print 'probe_points', self.probe_points, coords[self.probe_points[0]]
139 
140  #domain.write_mesh(cf.URI('tg-mesh.msh'))
141 
142  return mesh
143 
144  def setup_ic(self, u_tag, p_tag):
145  if self.modelname == 'implicit':
146  ic_comp = self.solver.InitialConditions
147  else:
148  ic_comp = self.solver.InitialConditions.NavierStokes
149  #initial condition for the velocity. Unset variables (i.e. the pressure) default to zero
150  ic_u = ic_comp.create_initial_condition(builder_name = 'cf3.UFEM.InitialConditionFunction', field_tag = u_tag)
151  ic_u.variable_name = 'Velocity'
152  ic_u.regions = [self.mesh.topology.interior.uri()]
153  ic_u.value = ['{Ua} - cos(pi/{D}*x)*sin(pi/{D}*y)'.format(Ua = self.Ua, D = self.D), '{Va} + sin(pi/{D}*x)*cos(pi/{D}*y)'.format(Va = self.Va, D = self.D)]
154 
155  ic_p = ic_comp.create_initial_condition(builder_name = 'cf3.UFEM.InitialConditionFunction', field_tag = p_tag)
156  ic_p.regions = [self.mesh.topology.interior.uri()]
157  ic_p.variable_name = 'Pressure'
158  ic_p.value = ['-0.25*(cos(2*pi/{D}*x) + cos(2*pi/{D}*y))'.format(D = self.D)]
159 
160  ic_u.execute()
161  ic_p.execute()
162 
163  def setup_model(self):
164  if self.model != None:
165  self.model.delete_component()
166 
167  model = cf.Core.root().create_component('NavierStokes', 'cf3.solver.ModelUnsteady')
168  self.model = model
169  domain = model.create_domain()
170  physics = model.create_physics('cf3.UFEM.NavierStokesPhysics')
171  self.solver = model.create_solver('cf3.UFEM.Solver')
172 
173  # Physical constants
174  physics.density = 1.
175  physics.dynamic_viscosity = 0.001
176 
177  return self.solver
178 
179  def add_pressure_bc(self, bc, var_name = 'Pressure'):
180  bc.regions = [self.mesh.topology.uri()]
181  nu = self.model.NavierStokesPhysics.kinematic_viscosity
182  bc.add_function_bc(region_name = 'center', variable_name = var_name).value = ['-0.25 * (cos(2*pi/{D}*(x - {Ua}*(t+{dt}))) + cos(2*pi/{D}*(y - {Va}*(t+{dt})))) * exp(-4*{nu}*pi^2/{D}^2*(t+{dt})) '.format(D = self.D, nu = nu, Ua = self.Ua, Va = self.Va, dt = self.dt)]
183 
184  def setup_implicit(self, segments, Ua, Va, D, theta):
185  self.Ua = Ua
186  self.Va = Va
187  self.D = D
188  self.segments = segments
189 
190  self.modelname = 'implicit'
191 
192  solver = self.setup_model()
193  ns_solver = solver.add_unsteady_solver('cf3.UFEM.NavierStokes')
194  ns_solver.options.theta = theta
195  ns_solver.options.use_specializations = False
196  self.theta = theta
197 
198  mesh = self.create_mesh(segments)
199  ns_solver.regions = [mesh.topology.interior.uri()]
200 
201  self.add_pressure_bc(ns_solver.BoundaryConditions)
202 
203  lss = ns_solver.create_lss(matrix_builder = 'cf3.math.LSS.TrilinosFEVbrMatrix', solution_strategy = 'cf3.math.LSS.TrilinosStratimikosStrategy')
204  #lss.SolutionStrategy.Parameters.linear_solver_type = 'Amesos'
205  # lss.SolutionStrategy.Parameters.LinearSolverTypes.Amesos.solver_type = 'Mumps'
206  #lss.SolutionStrategy.Parameters.LinearSolverTypes.Amesos.create_parameter_list('Amesos Settings').add_parameter(name = 'MaxProcs', value=1)
207  #lss.SolutionStrategy.Parameters.LinearSolverTypes.Amesos.AmesosSettings.add_parameter(name = 'Redistribute', value=True)
208  #lss.SolutionStrategy.Parameters.LinearSolverTypes.Amesos.AmesosSettings.create_parameter_list('Mumps').add_parameter(name='Equilibrate', value = False)
209 
210  solver.create_fields()
211  self.setup_ic('navier_stokes_solution', 'navier_stokes_solution')
212 
213  # kinetic_energy = solver.add_unsteady_solver('cf3.UFEM.KineticEnergyIntegral')
214  # kinetic_energy.regions = [mesh.topology.interior.uri()]
215  # kinetic_energy.history = solver.create_component('KEHistory', 'cf3.solver.History')
216  # kinetic_energy.history.file = cf.URI('ke-history.tsv')
217  # kinetic_energy.history.dimension = 1
218 
219  def setup_semi_implicit(self, segments, Ua, Va, D, theta):
220  self.Ua = Ua
221  self.Va = Va
222  self.D = D
223  self.segments = segments
224 
225  self.modelname = 'semi'
226 
227  solver = self.setup_model()
228  ns_solver = solver.add_unsteady_solver('cf3.UFEM.NavierStokesSemiImplicit')
229 
230  ns_solver.options.theta = theta
231  ns_solver.options.nb_iterations = 2
232  self.theta = theta
233  #ns_solver.children.GlobalLSS.options.blocked_system = False
234  #ns_solver.PressureLSS.solution_strategy = 'cf3.math.LSS.DirectStrategy'
235 
236  mesh = self.create_mesh(segments)
237  ns_solver.regions = [mesh.topology.interior.uri()]
238 
239  ns_solver.PressureLSS.LSS.SolutionStrategy.Parameters.linear_solver_type = 'Amesos'
240  ns_solver.VelocityLSS.LSS.SolutionStrategy.Parameters.linear_solver_type = 'Amesos'
241  ns_solver.PressureLSS.LSS.SolutionStrategy.print_settings = False
242  ns_solver.VelocityLSS.LSS.SolutionStrategy.print_settings = False
243 
244  self.add_pressure_bc(ns_solver.PressureLSS.BC)
245 
246  solver.create_fields()
247  self.setup_ic('navier_stokes_u_solution', 'navier_stokes_p_solution')
248 
249  def iterate(self, numsteps, save_interval = 1, process_interval = 1):
250 
251  tstep = self.dt
252 
253  if (numsteps % save_interval) != 0:
254  raise RuntimeError('Number of time steps cannot be divided by save_interval')
255 
256  self.basename = '{modelname}-{element}-{segments}-dt_{tstep}-theta_{theta}'.format(modelname = self.modelname, element = self.element, segments = self.segments, tstep = tstep, theta = self.theta)
257  if not os.path.exists(self.basename) and cf.Core.rank() == 0:
258  os.makedirs(self.basename)
259 
260  self.outfile = open('uv_error-{modelname}-{element}-{segments}-dt_{tstep}-theta_{theta}-P{rank}.txt'.format(modelname = self.modelname, element = self.element, segments = self.segments, tstep = tstep, theta = self.theta, rank = cf.Core.rank()), 'w', 1)
261  self.outfile.write('# time (s), max u error, max v error, max p error')
262  for i in range(len(self.probe_points)):
263  self.outfile.write(', probe {probe} u error, probe {probe} v error, probe {probe} p error'.format(probe = i))
264  self.outfile.write('\n')
265 
266  # Time setup
267  time = self.model.create_time()
268  time.time_step = tstep
269 
270  # Setup a time series write
271  final_end_time = numsteps*tstep
272  self.iteration = 0
273  time.end_time = 0.
274 
275  # Resize the error array
276  self.max_error = np.zeros((3, numsteps))
277  self.t = np.zeros(numsteps)
278 
279  while time.current_time < final_end_time:
280  time.end_time += tstep
281  self.model.simulate()
282  #self.model.Solver.TimeLoop.NavierStokesExplicit.InnerLoop.PressureSystem.LSS.print_system('pressure_system.plt')
283  self.t[self.iteration] = time.current_time
284  if (self.iteration % process_interval == 0) or time.current_time >= final_end_time:
285  self.check_result(time.current_time >= final_end_time)
286  if self.iteration % save_interval == 0:
287  self.model.Domain.write_mesh(cf.URI(self.basename+'/taylor-green-' +str(self.iteration) + '.pvtu'))
288  self.iteration += 1
289  if self.iteration == 1:
290  self.model.Solver.options.disabled_actions = ['InitialConditions']
291  self.outfile.close()
292 
293  # print timings
294  self.model.print_timing_tree()
295 
296 
297  def check_result(self, dumpfile = False):
298  t = self.t[self.iteration]
299  Ua = self.Ua
300  Va = self.Va
301  D = self.D
302 
303  nu = self.model.NavierStokesPhysics.kinematic_viscosity
304 
305  try:
306  u_sol = self.mesh.geometry.navier_stokes_solution
307  p_sol = self.mesh.geometry.navier_stokes_solution
308  u_idx = 0
309  v_idx = 1
310  p_idx = 2
311  except AttributeError:
312  u_sol = self.mesh.geometry.navier_stokes_u_solution
313  p_sol = self.mesh.geometry.navier_stokes_p_solution
314  u_idx = 0
315  v_idx = 1
316  p_idx = 0
317 
318  coords = self.mesh.geometry.coordinates
319  x_arr = np.zeros(len(coords))
320  y_arr = np.zeros(len(coords))
321  p_num = np.zeros(len(coords))
322  u_num = np.zeros(len(coords))
323  v_num = np.zeros(len(coords))
324  p_th = np.zeros(len(coords))
325  u_th = np.zeros(len(coords))
326  v_th = np.zeros(len(coords))
327  for i in self.sample_coords:
328  (x, y) = (x_arr[i], y_arr[i]) = coords[i]
329  (u_num[i], v_num[i], p_num[i]) = ( u_sol[i][u_idx], u_sol[i][v_idx], p_sol[i][p_idx] )
330  u_th[i] = Ua - np.cos(np.pi/D*(x-Ua*t))*np.sin(np.pi/D*(y-Va*t))*np.exp(-2.*nu*np.pi**2/D**2*t)
331  v_th[i] = Va + np.sin(np.pi/D*(x-Ua*t))*np.cos(np.pi/D*(y-Va*t))*np.exp(-2.*nu*np.pi**2/D**2*t)
332  p_th[i] = -0.25 * (np.cos(2*np.pi/D*(x - Ua*t)) + np.cos(2*np.pi/D*(y - Va*t)))*np.exp(-4.*nu*np.pi**2/D**2*t)
333 
334  self.max_error[0, self.iteration] = np.max(np.abs(u_th - u_num))
335  self.max_error[1, self.iteration] = np.max(np.abs(v_th - v_num))
336  self.max_error[2, self.iteration] = np.max(np.abs(p_th - p_num))
337 
338  self.outfile.write('{t},{u},{v},{p}'.format(t = t, u = self.max_error[0, self.iteration], v = self.max_error[1, self.iteration], p = self.max_error[2, self.iteration]))
339  for i in self.probe_points:
340  self.outfile.write(',{u},{v},{p}'.format(u = u_th[i] - u_num[i], v = v_th[i] - v_num[i], p = p_th[i] - p_num[i]))
341  self.outfile.write('\n')
342  if self.iteration > 3:
343  if self.max_error[0, self.iteration] > 0.0014:
344  raise Exception('u error is too great')
345  if self.max_error[1, self.iteration] > 0.0014:
346  raise Exception('v error is too great')
347  if self.max_error[2, self.iteration] > 0.0033:
348  raise Exception('p error is too great')
349 
350 parser = OptionParser()
351 parser.add_option('--dt', type='float')
352 parser.add_option('--elem', type='string')
353 parser.add_option('--segs', type='int')
354 parser.add_option('--theta', type='float')
355 parser.add_option('--tsteps', type='int')
356 (options, args) = parser.parse_args()
357 
358 taylor_green_impl = TaylorGreen(dt = options.dt, element=options.elem)
359 taylor_green_impl.setup_implicit(options.segs, 0.3, 0.2, D=0.5, theta=options.theta)
360 taylor_green_impl.iterate(options.tsteps, 1, 1)
361 
362 taylor_green_semi = TaylorGreen(dt = options.dt, element=options.elem)
363 taylor_green_semi.setup_semi_implicit(options.segs, 0.3, 0.2, D=0.5, theta=options.theta)
364 taylor_green_semi.iterate(options.tsteps, 1, 1)
boost::python::object create_component(ComponentWrapper &self, const std::string &name, const std::string &builder_name)
Send comments to:
COOLFluiD Web Admin