source: anuga_core/source/anuga_parallel/test_parallel_sw.py @ 3586

Last change on this file since 3586 was 3586, checked in by ole, 17 years ago

Moved parallel api

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