Merge lp:~michael-lange/fluidity/fix_detector_init into lp:fluidity

Proposed by Michael Lange
Status: Merged
Approved by: Mark Filipiak
Approved revision: 4031
Merged at revision: 4127
Proposed branch: lp:~michael-lange/fluidity/fix_detector_init
Merge into: lp:fluidity
Diff against target: 325 lines (+235/-19)
6 files modified
femtools/Diagnostic_variables.F90 (+18/-17)
femtools/Node_Owner_Finder_Fortran.F90 (+13/-2)
tests/detectors_parallel_init/Makefile (+15/-0)
tests/detectors_parallel_init/detectors.flml (+121/-0)
tests/detectors_parallel_init/detectors_parallel_init.xml (+61/-0)
tests/detectors_parallel_init/src/square.geo (+7/-0)
To merge this branch: bzr merge lp:~michael-lange/fluidity/fix_detector_init
Reviewer Review Type Date Requested Status
Mark Filipiak (community) Approve
Review via email: mp+119699@code.launchpad.net

Description of the change

Fixing the initialisation of detectors in parallel (lp:967093) and adding an according test case. Many thanks to M. Filipiak for providing the patch.

Also fixing detector initialisation from file in parallel, which would previously segfault, due to the legacy restriction to only one proc.

To post a comment you must log in.
4030. By Michael Lange

Merge from trunk

4031. By Michael Lange

The new test case should use flredecomp.

Revision history for this message
Mark Filipiak (mjf-q) wrote :

Not sure if I'm allowed to review the changes since I'm one of the authors but I'd like to get this fix into the trunk so I can then add the fldecomp-to-flredecomp change.

The change to get the detectors read in from file in parallel looks ok (and matches what is done for a checkpointed detector file in parallel). The new test fails on the old trunk and passes with this branch.

I looked again at the code I added to work out the owner of a detector. I still think it's OK. It's has a slight inefficiency as James Maddison noticed but I don't know if changing the picker construction to consider only owned elements will break other things (e.g. interpolate_boundary_values(Geostrophic_Pressure.F90)). Changing find_serial() to have the same ownership test as find_parallel() might *seem* cleaner but will certainly break interpolate_boundary_values(Geostrophic_Pressure.F90).

I think the names of the routine find_serial() and find_parallel() are perhaps not descriptive, the first really means 'find any element, that this process has in its mesh, that contains the point, even if this process doesn't own that element': I don't think it is worth changing the names.

It can be merged into the trunk (Michael, I have a version of fix_detector_init that I merged trunk r4125 into and tested up to medium tests locally, not in buildbot).

review: Approve
4032. By Michael Lange

Merge from trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'femtools/Diagnostic_variables.F90'
2--- femtools/Diagnostic_variables.F90 2012-01-20 15:54:44 +0000
3+++ femtools/Diagnostic_variables.F90 2012-11-08 12:08:22 +0000
4@@ -1369,7 +1369,10 @@
5 assert(xfield%dim+1==local_coord_count(shape))
6
7 ! Determine element and local_coords from position
8- call picker_inquire(xfield,position,element,local_coord=lcoords,global=.false.)
9+ ! In parallel, global=.false. can often work because there will be
10+ ! a halo of non-owned elements in your process and so you can work out
11+ ! ownership without communication. But in general it won't work.
12+ call picker_inquire(xfield,position,element,local_coord=lcoords,global=.true.)
13
14 ! If we're in parallel and don't own the element, skip this detector
15 if (isparallel()) then
16@@ -1568,26 +1571,24 @@
17 else
18
19 ! Reading from a binary file where the user has placed the detector positions
20- if (getprocno() == 1) then
21- default_stat%detector_file_unit=free_unit()
22- call get_option("/io/detectors/detector_array/from_file/file_name",detector_file_filename)
23+ default_stat%detector_file_unit=free_unit()
24+ call get_option("/io/detectors/detector_array/from_file/file_name",detector_file_filename)
25
26 #ifdef STREAM_IO
27- open(unit = default_stat%detector_file_unit, file = trim(detector_file_filename), &
28- & action = "read", access = "stream", form = "unformatted")
29+ open(unit = default_stat%detector_file_unit, file = trim(detector_file_filename), &
30+ & action = "read", access = "stream", form = "unformatted")
31 #else
32- FLAbort("No stream I/O support")
33+ FLAbort("No stream I/O support")
34 #endif
35-
36- do j=1,ndete
37- write(detector_name, fmt) trim(funcnam)//"_", j
38- default_stat%detector_list%detector_names(k)=trim(detector_name)
39- read(default_stat%detector_file_unit) detector_location
40- call create_single_detector(default_stat%detector_list, xfield, &
41- detector_location, k, type_det, trim(detector_name))
42- k=k+1
43- end do
44- end if
45+
46+ do j=1,ndete
47+ write(detector_name, fmt) trim(funcnam)//"_", j
48+ default_stat%detector_list%detector_names(k)=trim(detector_name)
49+ read(default_stat%detector_file_unit) detector_location
50+ call create_single_detector(default_stat%detector_list, xfield, &
51+ detector_location, k, type_det, trim(detector_name))
52+ k=k+1
53+ end do
54 end if
55 end do
56 else
57
58=== modified file 'femtools/Node_Owner_Finder_Fortran.F90'
59--- femtools/Node_Owner_Finder_Fortran.F90 2010-11-09 14:08:19 +0000
60+++ femtools/Node_Owner_Finder_Fortran.F90 2012-11-08 12:08:22 +0000
61@@ -268,8 +268,16 @@
62 call cnode_owner_finder_query_output(id, nele_ids)
63
64 closest_ele_id = -1
65- do j = 1, nele_ids
66+ possible_elements_loop: do j = 1, nele_ids
67 call cnode_owner_finder_get_output(id, possible_ele_id, j)
68+ ! If this process does not own this possible_ele_id element then
69+ ! don't consider it. This filter is needed to make this subroutine work in
70+ ! parallel without having to use universal numbers, which aren't defined
71+ ! for all the meshes that use this subroutine.
72+ if(.not.element_owned(positions_a,possible_ele_id)) then
73+ assert(isparallel())
74+ cycle possible_elements_loop
75+ end if
76 ! Zero tolerance - we're not using an "epsilon-ball" approach here
77 if(ownership_predicate(positions_a, possible_ele_id, positions(:, i), 0.0, miss = miss)) then
78 ele_ids(i) = possible_ele_id
79@@ -281,7 +289,7 @@
80 closest_ele_id = possible_ele_id
81 closest_misses(i) = miss
82 end if
83- end do
84+ end do possible_elements_loop
85
86 ! We didn't find an owner, so choose the element with the closest miss
87 ele_ids(i) = closest_ele_id
88@@ -310,6 +318,9 @@
89 ! Another processes has a smaller miss for this coordinate
90 ele_ids(i) = -1
91 end if
92+ ! if no process has closest_misses(i) < out_of_bounds_tolerance
93+ ! then ele_ids(i) is already set to -1 in positions_loop above
94+ ! on all processes. This matches the find_serial(0) behaviour.
95 end do
96 #endif
97
98
99=== added directory 'tests/detectors_parallel_init'
100=== added file 'tests/detectors_parallel_init/Makefile'
101--- tests/detectors_parallel_init/Makefile 1970-01-01 00:00:00 +0000
102+++ tests/detectors_parallel_init/Makefile 2012-11-08 12:08:22 +0000
103@@ -0,0 +1,15 @@
104+default: input
105+
106+input: clean
107+ gmsh -2 -o src/square.msh src/square.geo
108+ ../../bin/gmsh2triangle --2d src/square.msh
109+ mpiexec -n 2 ../../bin/flredecomp -i 1 -o 2 detectors detectors_flredecomp
110+
111+clean: clean-mesh clean-run
112+clean-mesh:
113+ rm -f *.ele *.edge *.face *.node *.halo *.pvtu *.vtu *.detectors *.detectors.dat *.stat
114+ rm -f gmsh.log gmsh_err.log
115+clean-run:
116+ rm -f matrixdump matrixdump.info
117+ rm -f fluidity.err-* fluidity.log-*
118+ rm -rf detectors_[0-4]* *flredecomp*
119
120=== added file 'tests/detectors_parallel_init/detectors.flml'
121--- tests/detectors_parallel_init/detectors.flml 1970-01-01 00:00:00 +0000
122+++ tests/detectors_parallel_init/detectors.flml 2012-11-08 12:08:22 +0000
123@@ -0,0 +1,121 @@
124+<?xml version='1.0' encoding='utf-8'?>
125+<fluidity_options>
126+ <simulation_name>
127+ <string_value lines="1">detectors</string_value>
128+ </simulation_name>
129+ <problem_type>
130+ <string_value lines="1">fluids</string_value>
131+ </problem_type>
132+ <geometry>
133+ <dimension>
134+ <integer_value rank="0">2</integer_value>
135+ </dimension>
136+ <mesh name="CoordinateMesh">
137+ <from_file file_name="square">
138+ <format name="triangle"/>
139+ <stat>
140+ <include_in_stat/>
141+ </stat>
142+ </from_file>
143+ </mesh>
144+ <mesh name="VelocityMesh">
145+ <from_mesh>
146+ <mesh name="CoordinateMesh"/>
147+ <stat>
148+ <exclude_from_stat/>
149+ </stat>
150+ </from_mesh>
151+ </mesh>
152+ <quadrature>
153+ <degree>
154+ <integer_value rank="0">6</integer_value>
155+ </degree>
156+ </quadrature>
157+ </geometry>
158+ <io>
159+ <dump_format>
160+ <string_value>vtk</string_value>
161+ </dump_format>
162+ <dump_period>
163+ <constant>
164+ <real_value rank="0">0.0</real_value>
165+ </constant>
166+ </dump_period>
167+ <output_mesh name="VelocityMesh"/>
168+ <stat/>
169+ <detectors>
170+ <static_detector name="MidPoint">
171+ <location>
172+ <real_value shape="2" dim1="dim" rank="1">0.5 0.5</real_value>
173+ </location>
174+ </static_detector>
175+ <detector_array name="DArray">
176+ <number_of_detectors>
177+ <integer_value rank="0">3</integer_value>
178+ </number_of_detectors>
179+ <static/>
180+ <from_file file_name="positions.dat">
181+ <format>
182+ <string_value>binary</string_value>
183+ </format>
184+ </from_file>
185+ </detector_array>
186+ <fail_outside_domain/>
187+ </detectors>
188+ </io>
189+ <timestepping>
190+ <current_time>
191+ <real_value rank="0">0.0</real_value>
192+ </current_time>
193+ <timestep>
194+ <real_value rank="0">1.0</real_value>
195+ </timestep>
196+ <finish_time>
197+ <real_value rank="0">1.0</real_value>
198+ </finish_time>
199+ </timestepping>
200+ <physical_parameters/>
201+ <material_phase name="Water">
202+ <vector_field name="Velocity" rank="1">
203+ <prescribed>
204+ <mesh name="VelocityMesh"/>
205+ <value name="WholeMesh">
206+ <python>
207+ <string_value lines="20" type="code" language="python">def val(X,t):
208+ return(X[1],0.0)</string_value>
209+ </python>
210+ </value>
211+ <output/>
212+ <stat>
213+ <include_in_stat/>
214+ </stat>
215+ <detectors>
216+ <include_in_detectors/>
217+ </detectors>
218+ </prescribed>
219+ </vector_field>
220+ <scalar_field name="Tracer" rank="0">
221+ <prescribed>
222+ <mesh name="VelocityMesh"/>
223+ <value name="WholeMesh">
224+ <python>
225+ <string_value lines="20" type="code" language="python">def val(X,t):
226+ return X[0]</string_value>
227+ </python>
228+ </value>
229+ <output/>
230+ <stat/>
231+ <detectors>
232+ <include_in_detectors/>
233+ </detectors>
234+ </prescribed>
235+ </scalar_field>
236+ </material_phase>
237+ <flredecomp>
238+ <final_partitioner>
239+ <zoltan>
240+ <method>graph</method>
241+ </zoltan>
242+ </final_partitioner>
243+ </flredecomp>
244+</fluidity_options>
245
246=== added file 'tests/detectors_parallel_init/detectors_parallel_init.xml'
247--- tests/detectors_parallel_init/detectors_parallel_init.xml 1970-01-01 00:00:00 +0000
248+++ tests/detectors_parallel_init/detectors_parallel_init.xml 2012-11-08 12:08:22 +0000
249@@ -0,0 +1,61 @@
250+<?xml version="1.0" encoding="UTF-8" ?>
251+
252+<testproblem>
253+ <name>detectors_parallel_init</name>
254+ <owner userid="mlange"/>
255+ <tags>flml</tags>
256+ <problem_definition length="short" nprocs="1">
257+ <command_line>mpiexec -n 2 ../../bin/fluidity detectors_flredecomp.flml </command_line>
258+ <!-- Test that detectors are initialised correctly in parallel. -->
259+ </problem_definition>
260+ <variables>
261+ <variable name="solvers_converged" language="python">
262+import os
263+files = os.listdir("./")
264+solvers_converged = not "matrixdump" in files and not "matrixdump.info" in files
265+ </variable>
266+ <variable name = "time" language = "python">
267+from fluidity_tools import stat_parser
268+time = stat_parser("detectors.stat")["ElapsedTime"]["value"]
269+ </variable>
270+ <variable name = "det_midpoint" language = "python">
271+from fluidity_tools import stat_parser
272+det_midpoint = stat_parser("detectors.detectors")["MidPoint"]['position']
273+ </variable>
274+ <variable name = "det_arr1" language = "python">
275+from fluidity_tools import stat_parser
276+det_arr1 = stat_parser("detectors.detectors")["DArray_1"]['position']
277+ </variable>
278+ <variable name = "det_arr2" language = "python">
279+from fluidity_tools import stat_parser
280+det_arr2 = stat_parser("detectors.detectors")["DArray_2"]['position']
281+ </variable>
282+ <variable name = "det_arr3" language = "python">
283+from fluidity_tools import stat_parser
284+det_arr3 = stat_parser("detectors.detectors")["DArray_3"]['position']
285+ </variable>
286+ </variables>
287+ <pass_tests>
288+ <test name="Solvers converged" language="python">
289+ assert(solvers_converged)
290+ </test>
291+ <test name="Test finished" language="python">
292+assert abs(time - 1.0) &lt; 1.0e-6
293+ </test>
294+ <test name="Detector output" language="python">
295+assert abs(len(time) - len(det_midpoint[-1])) &lt; 1.0e-6
296+ </test>
297+ <test name="Detectors initialised correctly" language="python">
298+assert abs(det_midpoint[0] - 0.5).all() &lt; 1.0e-6
299+assert abs(det_midpoint[1] - 0.5).all() &lt; 1.0e-6
300+assert abs(det_arr1[0]).all() &lt; 1.0e-6
301+assert abs(det_arr1[1] - 1.0).all() &lt; 1.0e-6
302+assert abs(det_arr2[0] - 0.5).all() &lt; 1.0e-6
303+assert abs(det_arr2[1] - 0.5).all() &lt; 1.0e-6
304+assert abs(det_arr3[0] - 1.0).all() &lt; 1.0e-6
305+assert abs(det_arr3[1]).all() &lt; 1.0e-6
306+ </test>
307+ </pass_tests>
308+ <warn_tests>
309+ </warn_tests>
310+</testproblem>
311
312=== added file 'tests/detectors_parallel_init/positions.dat'
313Binary files tests/detectors_parallel_init/positions.dat 1970-01-01 00:00:00 +0000 and tests/detectors_parallel_init/positions.dat 2012-11-08 12:08:22 +0000 differ
314=== added directory 'tests/detectors_parallel_init/src'
315=== added file 'tests/detectors_parallel_init/src/square.geo'
316--- tests/detectors_parallel_init/src/square.geo 1970-01-01 00:00:00 +0000
317+++ tests/detectors_parallel_init/src/square.geo 2012-11-08 12:08:22 +0000
318@@ -0,0 +1,7 @@
319+Point (1) = {0, 0, 0};
320+Extrude {1,0,0} {
321+ Point{1}; Layers{2};
322+}
323+Extrude {0,1,0} {
324+ Line{1}; Layers{2};
325+}