source: inundation/parallel/test_parallel_sw.py @ 2776

Last change on this file since 2776 was 2776, checked in by jack, 19 years ago

Update to the parallel shallow water test case.

  • Property svn:executable set to *
File size: 8.4 KB
Line 
1#!/usr/bin/env python
2# Test a run of the sequential shallow water domain against
3# a run of the parallel shallow water domain.
4# WARNING: This assumes that the command to run jobs is mpirun.
5# Tested with MPICH.
6
7mesh_filename = "merimbula_10785.tsh"
8yieldstep = 1
9finaltime = 60
10quantity = 'stage'
11nprocs = 8
12
13import unittest
14import os
15import sys
16import print_stats
17import pypar
18
19from Numeric import array, zeros, Float, take, nonzero
20from shallow_water import Domain
21from shallow_water import Reflective_boundary as sw_reflective_boundary
22from shallow_water import Transmissive_boundary as sw_transmissive_boundary
23from parallel_shallow_water import Parallel_Domain
24from parallel_shallow_water import Reflective_boundary as par_reflective_boundary
25from parallel_shallow_water import Transmissive_boundary as par_transmissive_boundary
26from pmesh2domain import pmesh_to_domain_instance
27from utilities.norms import *
28from utilities.util_ext import double_precision
29from print_stats import print_test_stats, build_full_flag
30from pmesh_divide import pmesh_divide_metis
31from build_submesh import build_submesh, extract_hostmesh
32from build_local import build_local_mesh
33from build_commun import send_submesh, rec_submesh
34
35class Set_Stage:
36    """Set an initial condition with constant water height, for x<x0
37    """
38
39    def __init__(self, x0=0.25, x1=0.5, h=1.0):
40        self.x0 = x0
41        self.x1 = x1
42        self.= h
43
44    def __call__(self, x, y):
45        return self.h*((x>self.x0)&(x<self.x1))
46
47sys.path.append(".." + os.sep + "pyvolution")
48
49def parallel_test():
50    myid = pypar.rank()
51    numprocs = pypar.size()
52    proc_name = pypar.Get_processor_name()
53
54    rect = zeros(4,Float) # Buffer for results
55    if myid == 0:
56        # Partition
57        domain_full = pmesh_to_domain_instance(mesh_filename, Domain)
58        rect = array(domain_full.xy_extent, Float)
59       
60        domain_full.set_quantity('stage', Set_Stage(756000.0, 756500.0, 2.0))
61        domain_full.check_integrity()
62        domain_full.smooth = False
63        domain_full.reduction = min
64        domain_full.checkpoint = False
65        domain_full.visualise = False
66
67        nodes, triangles, boundary, triangles_per_proc, quantities = \
68               pmesh_divide_metis(domain_full, numprocs)
69
70        submesh = build_submesh(nodes, triangles, boundary,\
71                                quantities, triangles_per_proc)
72
73        for p in range(1, numprocs):
74            send_submesh(submesh, triangles_per_proc, p)
75
76        hostmesh = extract_hostmesh(submesh)
77        points, vertices, boundary, quantities, ghost_recv_dict, full_send_dict = \
78                build_local_mesh(hostmesh, 0, triangles_per_proc[0], numprocs)
79
80    else:
81        points, vertices, boundary, quantities, ghost_recv_dict, full_send_dict = \
82                rec_submesh(0)
83
84    pypar.broadcast(rect, 0)
85    domain = Parallel_Domain(points, vertices, boundary,
86                             full_send_dict = full_send_dict,
87                             ghost_recv_dict = ghost_recv_dict)
88    tri_full_flag = build_full_flag(domain, ghost_recv_dict)
89
90    domain.default_order = 1
91    R = par_reflective_boundary(domain)
92    domain.set_boundary({'outflow' : R, 'inflow' : R, 'inner' : R, 'exterior' : R, 'open' : R, 'ghost' : None})
93    domain.set_quantity('stage', quantities['stage'])
94    domain.set_quantity('elevation', quantities['elevation'])
95    domain.store = False
96
97    l1list = []
98    l2list = []
99    linflist = []
100    l1norm = zeros(3, Float)
101    l2norm = zeros(3, Float)
102    linfnorm = zeros(3, Float)
103    recv_norm = zeros(3, Float)
104    # Evolution
105    for t in domain.evolve(yieldstep = yieldstep, finaltime = finaltime):
106        edges = take(domain.quantities[quantity].edge_values, nonzero(tri_full_flag))
107        l1norm[0] = l1_norm(edges[:, 0])
108        l1norm[1] = l1_norm(edges[:, 1])
109        l1norm[2] = l1_norm(edges[:, 2])
110        l2norm[0] = pow(l2_norm(edges[:,0]), 2)
111        l2norm[1] = pow(l2_norm(edges[:,1]), 2)
112        l2norm[2] = pow(l2_norm(edges[:,2]), 2)
113        linfnorm[0] = linf_norm(edges[:,0])
114        linfnorm[1] = linf_norm(edges[:,1])
115        linfnorm[2] = linf_norm(edges[:,2])
116        if myid == 0:
117            domain.write_time()
118            for p in range(1, numprocs):
119                pypar.receive(p, recv_norm)
120                l1norm += recv_norm
121                pypar.receive(p, recv_norm)
122                l2norm += recv_norm
123                pypar.receive(p, recv_norm)
124                linfnorm[0] = max(linfnorm[0], recv_norm[0])
125                linfnorm[1] = max(linfnorm[1], recv_norm[1])
126                linfnorm[2] = max(linfnorm[2], recv_norm[2])
127            l1list.append(l1norm)
128            l2norm[0] = pow(l2norm[0], 0.5)
129            l2norm[1] = pow(l2norm[1], 0.5)
130            l2norm[2] = pow(l2norm[2], 0.5)
131            l2list.append(l2norm)
132            linflist.append(linfnorm)
133        else:
134            pypar.send(l1norm, 0)
135            pypar.send(l2norm, 0)
136            pypar.send(linfnorm, 0)
137    return (l1list, l2list, linflist)
138
139def sequential_test():
140    domain_full = pmesh_to_domain_instance(mesh_filename, Domain)
141
142    domain_full.set_quantity('stage', Set_Stage(756000.0, 756500.0, 2.0))
143    domain_full.check_integrity()
144    domain_full.default_order = 1
145    domain_full.smooth = False
146    domain_full.reduction = min
147    domain_full.store = False
148    domain_full.checkpoint = False
149    domain_full.visualise = False
150    R = sw_reflective_boundary(domain_full)
151    domain_full.set_boundary({'outflow' : R, 'inflow' : R, 'inner' : R, 'exterior' : R, 'open' : R})
152    l1list = []
153    l2list = []
154    linflist = []
155    l1norm = zeros(3, Float)
156    l2norm = zeros(3, Float)
157    linfnorm = zeros(3, Float)
158    for t in domain_full.evolve(yieldstep = yieldstep, finaltime = finaltime):
159        domain_full.write_time()
160        edge = domain_full.quantities[quantity].edge_values
161        l1norm[0] = l1_norm(edge[:,0])
162        l1norm[1] = l1_norm(edge[:,1])
163        l1norm[2] = l1_norm(edge[:,2])
164        l2norm[0] = l2_norm(edge[:,0])
165        l2norm[1] = l2_norm(edge[:,1])
166        l2norm[2] = l2_norm(edge[:,2])
167        linfnorm[0] = linf_norm(edge[:,0])
168        linfnorm[1] = linf_norm(edge[:,1])
169        linfnorm[2] = linf_norm(edge[:,2])
170        l1list.append(l1norm)
171        l2list.append(l2norm)
172        linflist.append(linfnorm)
173    return (l1list, l2list, linflist)
174
175# Test an 8-way run of the shallow water equations
176# against the sequential code.
177
178class Test_Parallel_Sw(unittest.TestCase):
179    def testParallelSw(self):
180        print "Expect this test to fail if not run from the parallel directory."
181        result = os.system("mpirun -np %d test_parallel_sw.py" % nprocs)
182        assert result == 0
183
184# Because we are doing assertions outside of the TestCase class
185# the PyUnit defined assert_ function can't be used.
186def assert_(condition, msg="Assertion Failed"):
187    if condition == False:
188        raise AssertionError, msg
189
190if __name__=="__main__":
191    if pypar.size() == 1: 
192        runner = unittest.TextTestRunner()
193        suite = unittest.makeSuite(Test_Parallel_Sw, 'test')
194        runner.run(suite)
195    else:
196        if pypar.rank() == 0:
197            l1norm_seq, l2norm_seq, linfnorm_seq = sequential_test()
198        l1norm_par, l2norm_par, linfnorm_par = parallel_test()
199        if pypar.rank() == 0:
200            assert_(len(l1norm_seq) == len(l1norm_par))
201            assert_(len(l2norm_seq) == len(l2norm_par))
202            assert_(len(linfnorm_seq) == len(linfnorm_par))
203            assert_(len(l1norm_seq) == len(l2norm_seq))
204            assert_(len(l2norm_seq) == len(linfnorm_seq))
205            # Anything smaller than tol we consider to be 0.
206            tol = pow(10, -1 * double_precision())
207            for x in range(len(l1norm_seq)):
208                for y in range(3):
209                    assert_((l1norm_seq[x][y] - l1norm_par[x][y]) < tol)
210                    assert_((l2norm_seq[x][y] - l2norm_par[x][y]) < tol)
211                    assert_((linfnorm_seq[x][y] - linfnorm_par[x][y]) < tol)
212                    if x > 0:
213                        assert_((l1norm_seq[x][y] - l1norm_seq[x-1][y]) < tol)
214                        assert_((l2norm_seq[x][y] - l2norm_seq[x-1][y]) < tol)
215                        assert_((linfnorm_seq[x][y] - linfnorm_seq[x-1][y]) < tol)
216                        assert_((l1norm_par[x][y] - l1norm_par[x-1][y]) < tol)
217                        assert_((l2norm_par[x][y] - l2norm_par[x-1][y]) < tol)
218                        assert_((linfnorm_par[x][y] - linfnorm_par[x-1][y]) < tol)
219        pypar.finalize()
220
Note: See TracBrowser for help on using the repository browser.