WIP: Pull Request for a complete Solver package #1
| @@ -288,8 +288,6 @@ void commPartition(Comm* c, int jmax, int imax) | ||||
|  | ||||
| void commUpdateDatatypes(Comm* oldcomm, Comm* newcomm, int imaxLocal, int jmaxLocal) | ||||
| { | ||||
|     Comm* newcomm; | ||||
|  | ||||
| #if defined _MPI | ||||
|     newcomm->comm = MPI_COMM_NULL; | ||||
|     int result = MPI_Comm_dup(oldcomm->comm, &newcomm->comm); | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
|  | ||||
| #define FINEST_LEVEL   0 | ||||
| #define COARSEST_LEVEL (s->levels - 1) | ||||
| #define S(i, j)        s[(j) * (imaxLocal + 2) + (i)] | ||||
| // #define S(i, j)        s[(j) * (imaxLocal + 2) + (i)] | ||||
| #define E(i, j)        e[(j) * (imaxLocal + 2) + (i)] | ||||
| #define R(i, j)        r[(j) * (imaxLocal + 2) + (i)] | ||||
| #define OLD(i, j)      old[(j) * (imaxLocal + 2) + (i)] | ||||
|   | ||||
							
								
								
									
										87
									
								
								EnhancedSolver/2D-mpi/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								EnhancedSolver/2D-mpi/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| #======================================================================================= | ||||
| # Copyright (C) NHR@FAU, University Erlangen-Nuremberg. | ||||
| # All rights reserved. | ||||
| # Use of this source code is governed by a MIT-style | ||||
| # license that can be found in the LICENSE file. | ||||
| #======================================================================================= | ||||
|  | ||||
| #CONFIGURE BUILD SYSTEM | ||||
| TARGET	   = exe-$(TAG) | ||||
| BUILD_DIR  = ./$(TAG) | ||||
| SRC_DIR    = ./src | ||||
| MAKE_DIR   = ./ | ||||
| Q         ?= @ | ||||
|  | ||||
| #DO NOT EDIT BELOW | ||||
| include $(MAKE_DIR)/config.mk | ||||
| include $(MAKE_DIR)/include_$(TAG).mk | ||||
| INCLUDES  += -I$(SRC_DIR) -I$(BUILD_DIR) | ||||
|  | ||||
| VPATH     = $(SRC_DIR) | ||||
| SRC       = $(filter-out $(wildcard $(SRC_DIR)/*-*.c),$(wildcard $(SRC_DIR)/*.c)) | ||||
| ASM       = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.s, $(SRC)) | ||||
| OBJ       = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC)) | ||||
| OBJ      += $(BUILD_DIR)/comm-$(COMM_TYPE).o | ||||
| OBJ      += $(BUILD_DIR)/solver-$(SOLVER).o | ||||
| SOURCES   = $(SRC) $(wildcard $(SRC_DIR)/*.h) | ||||
| CPPFLAGS := $(CPPFLAGS) $(DEFINES) $(OPTIONS) $(INCLUDES) | ||||
|  | ||||
| ${TARGET}: $(BUILD_DIR) $(OBJ) | ||||
| 	$(info ===>  LINKING  $(TARGET)) | ||||
| 	$(Q)${LINKER} ${LFLAGS} -o $(TARGET) $(OBJ) $(LIBS) | ||||
|  | ||||
| $(BUILD_DIR)/%.o:  %.c $(MAKE_DIR)/include_$(TAG).mk $(MAKE_DIR)/config.mk | ||||
| 	$(info ===>  COMPILE  $@) | ||||
| 	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@ | ||||
| 	$(Q)$(GCC) $(CPPFLAGS) -MT $(@:.d=.o) -MM  $< > $(BUILD_DIR)/$*.d | ||||
|  | ||||
| $(BUILD_DIR)/%.s:  %.c | ||||
| 	$(info ===>  GENERATE ASM  $@) | ||||
| 	$(CC) -S $(CPPFLAGS) $(CFLAGS) $< -o $@ | ||||
|  | ||||
| .PHONY: clean distclean vis_clean vis tags info asm format | ||||
|  | ||||
| vis: | ||||
| 	$(info ===>  GENERATE VISUALIZATION) | ||||
| 	@gnuplot -e "filename='pressure.dat'" ./surface.plot | ||||
| 	@gnuplot -e "filename='velocity.dat'" ./vector.plot | ||||
|  | ||||
| vis_clean: | ||||
| 	$(info ===>  CLEAN VISUALIZATION) | ||||
| 	@rm -f *.dat | ||||
| 	@rm -f *.png | ||||
| 	@rm -f ./vis_files/*.dat | ||||
| 	@rm -f ./vis_files/*.gif | ||||
|  | ||||
| clean: vis_clean | ||||
| 	$(info ===>  CLEAN) | ||||
| 	@rm -rf $(BUILD_DIR) | ||||
| 	@rm -f tags | ||||
|  | ||||
| distclean: clean | ||||
| 	$(info ===>  DIST CLEAN) | ||||
| 	@rm -f $(TARGET) | ||||
| 	@rm -f *.dat | ||||
| 	@rm -f *.png | ||||
|  | ||||
| info: | ||||
| 	$(info $(CFLAGS)) | ||||
| 	$(Q)$(CC) $(VERSION) | ||||
|  | ||||
| asm:  $(BUILD_DIR) $(ASM) | ||||
|  | ||||
| tags: | ||||
| 	$(info ===>  GENERATE TAGS) | ||||
| 	$(Q)ctags -R | ||||
|  | ||||
| format: | ||||
| 	@for src in $(SOURCES) ; do \ | ||||
| 		echo "Formatting $$src" ; \ | ||||
| 		clang-format -i $$src ; \ | ||||
| 	done | ||||
| 	@echo "Done" | ||||
|  | ||||
| $(BUILD_DIR): | ||||
| 	@mkdir $(BUILD_DIR) | ||||
|  | ||||
| -include $(OBJ:.o=.d) | ||||
							
								
								
									
										48
									
								
								EnhancedSolver/2D-mpi/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								EnhancedSolver/2D-mpi/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| # C source skeleton | ||||
|  | ||||
| ## Build | ||||
|  | ||||
| 1. Configure the toolchain and additional options in `config.mk`: | ||||
| ``` | ||||
| # Supported: GCC, CLANG, ICC | ||||
| TAG ?= GCC | ||||
| ENABLE_OPENMP ?= false | ||||
|  | ||||
| OPTIONS +=  -DARRAY_ALIGNMENT=64 | ||||
| #OPTIONS +=  -DVERBOSE_AFFINITY | ||||
| #OPTIONS +=  -DVERBOSE_DATASIZE | ||||
| #OPTIONS +=  -DVERBOSE_TIMER | ||||
| ``` | ||||
|  | ||||
| The verbosity options enable detailed output about affinity settings, allocation sizes and timer resolution. | ||||
|  | ||||
|  | ||||
| 2. Build with: | ||||
| ``` | ||||
| make | ||||
| ``` | ||||
|  | ||||
| You can build multiple toolchains in the same directory, but notice that the Makefile is only acting on the one currently set. | ||||
| Intermediate build results are located in the `<TOOLCHAIN>` directory. | ||||
|  | ||||
| To output the executed commands use: | ||||
| ``` | ||||
| make Q= | ||||
| ``` | ||||
|  | ||||
| 3. Clean up with: | ||||
| ``` | ||||
| make clean | ||||
| ``` | ||||
| to clean intermediate build results. | ||||
|  | ||||
| ``` | ||||
| make distclean | ||||
| ``` | ||||
| to clean intermediate build results and binary. | ||||
|  | ||||
| 4. (Optional) Generate assembler: | ||||
| ``` | ||||
| make asm | ||||
| ``` | ||||
| The assembler files will also be located in the `<TOOLCHAIN>` directory. | ||||
							
								
								
									
										79
									
								
								EnhancedSolver/2D-mpi/backstep.par
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								EnhancedSolver/2D-mpi/backstep.par
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #============================================================================== | ||||
| #                            Laminar Canal Flow | ||||
| #============================================================================== | ||||
|  | ||||
| # Problem specific Data: | ||||
| # --------------------- | ||||
|  | ||||
| name backstep             # name of flow setup | ||||
|  | ||||
| bcTop      1			#  flags for boundary conditions | ||||
| bcBottom   1			#  1 = no-slip      3 = outflow | ||||
| bcLeft     3			#  2 = free-slip    4 = periodic | ||||
| bcRight    3			# | ||||
|  | ||||
| gx    0.0      # Body forces (e.g. gravity) | ||||
| gy    0.0      # | ||||
|  | ||||
| re    36000.0	   # Reynolds number | ||||
|  | ||||
| u_init    1.0      # initial value for velocity in x-direction | ||||
| v_init    0.0      # initial value for velocity in y-direction | ||||
| p_init    1.0      # initial value for pressure | ||||
|  | ||||
| # Geometry Data: | ||||
| # ------------- | ||||
|  | ||||
| xlength    7.0     # domain size in x-direction | ||||
| ylength    1.5	   # domain size in y-direction | ||||
| imax       210     # number of interior cells in x-direction | ||||
| jmax       45	   # number of interior cells in y-direction | ||||
|  | ||||
| # Time Data: | ||||
| # --------- | ||||
|  | ||||
| te      60.0    # final time | ||||
| dt      0.02    # time stepsize | ||||
| tau     0.5     # safety factor for time stepsize control (<0 constant delt) | ||||
|  | ||||
| # Pressure Iteration Data: | ||||
| # ----------------------- | ||||
|  | ||||
| itermax  500       # maximal number of pressure iteration in one time step | ||||
| eps      0.0001    # stopping tolerance for pressure iteration | ||||
| rho      0.52 | ||||
| omg      1.8       # relaxation parameter for SOR iteration | ||||
| gamma    0.9       # upwind differencing factor gamma | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        3         # Multigrid levels | ||||
| presmooth     15        # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|  | ||||
| numberOfParticles   200 | ||||
| startTime           0     #if you want to see particles trapped in recirculation zone, startTime should be set to 0  | ||||
| injectTimePeriod    1.0 | ||||
| writeTimePeriod     0.5 | ||||
|  | ||||
| x1                  0.0 | ||||
| y1                  0.5 | ||||
| x2                  0.0 | ||||
| y2                  1.5 | ||||
|  | ||||
| # Obstacle Geometry Data: | ||||
| # ----------------------- | ||||
| # Shape 0 disable, 1 Rectangle/Square, 2 Circle | ||||
|  | ||||
| shape               1  | ||||
| xCenter             0.0 | ||||
| yCenter             0.0 | ||||
| xRectLength         2.0 | ||||
| yRectLength         1.0 | ||||
| circleRadius        1.0 | ||||
|  | ||||
| #=============================================================================== | ||||
							
								
								
									
										78
									
								
								EnhancedSolver/2D-mpi/canal.par
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								EnhancedSolver/2D-mpi/canal.par
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| #============================================================================== | ||||
| #                            Laminar Canal Flow | ||||
| #============================================================================== | ||||
|  | ||||
| # Problem specific Data: | ||||
| # --------------------- | ||||
|  | ||||
| name canal             # name of flow setup | ||||
|  | ||||
| bcTop      1			#  flags for boundary conditions | ||||
| bcBottom   1			#  1 = no-slip      3 = outflow | ||||
| bcLeft     3			#  2 = free-slip    4 = periodic | ||||
| bcRight    3			# | ||||
|  | ||||
| gx     0.0      # Body forces (e.g. gravity) | ||||
| gy     0.0      # | ||||
|  | ||||
| re            100.0	   # Reynolds number | ||||
|  | ||||
| u_init        1.0      # initial value for velocity in x-direction | ||||
| v_init        0.0      # initial value for velocity in y-direction | ||||
| p_init        0.0      # initial value for pressure | ||||
|  | ||||
| # Geometry Data: | ||||
| # ------------- | ||||
|  | ||||
| xlength       30.0     # domain size in x-direction | ||||
| ylength       4.0	   # domain size in y-direction | ||||
| imax          200      # number of interior cells in x-direction | ||||
| jmax          40	   # number of interior cells in y-direction | ||||
|  | ||||
| # Time Data: | ||||
| # --------- | ||||
|  | ||||
| te       60.0   # final time | ||||
| dt       0.02    # time stepsize | ||||
| tau      0.5     # safety factor for time stepsize control (<0 constant delt) | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        2         # Multigrid levels | ||||
| presmooth     5         # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Pressure Iteration Data: | ||||
| # ----------------------- | ||||
|  | ||||
| itermax       500       # maximal number of pressure iteration in one time step | ||||
| eps           0.00001   # stopping tolerance for pressure iteration | ||||
| omg           1.8       # relaxation parameter for SOR iteration | ||||
| gamma         0.9       # upwind differencing factor gamma | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|  | ||||
| numberOfParticles   60 | ||||
| startTime           10.0 | ||||
| injectTimePeriod    4.0 | ||||
| writeTimePeriod     1.0 | ||||
|  | ||||
| x1                  1.0 | ||||
| y1                  0.0 | ||||
| x2                  1.0 | ||||
| y2                  4.0 | ||||
|  | ||||
| # Obstacle Geometry Data: | ||||
| # ----------------------- | ||||
| # Shape 0 disable, 1 Rectangle/Square, 2 Circle | ||||
|  | ||||
| shape               0  | ||||
| xCenter             10.0 | ||||
| yCenter             2 | ||||
| xRectLength         6.0 | ||||
| yRectLength         1.0 | ||||
| circleRadius        1.0 | ||||
|  | ||||
| #=============================================================================== | ||||
							
								
								
									
										17
									
								
								EnhancedSolver/2D-mpi/config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								EnhancedSolver/2D-mpi/config.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # Supported: GCC, CLANG, ICC | ||||
| TAG ?= ICC | ||||
| # Supported: true, false | ||||
| ENABLE_MPI ?= true | ||||
| ENABLE_OPENMP ?= false | ||||
| # Supported: rb, mg | ||||
| SOLVER ?= mg | ||||
| # Run in debug settings ?= mg | ||||
| COMM_TYPE ?= v3 | ||||
|  | ||||
| #Feature options | ||||
| OPTIONS +=  -DARRAY_ALIGNMENT=64 | ||||
| OPTIONS +=  -DVERBOSE | ||||
| # OPTIONS +=  -DTEST | ||||
| #OPTIONS +=  -DVERBOSE_AFFINITY | ||||
| #OPTIONS +=  -DVERBOSE_DATASIZE | ||||
| #OPTIONS +=  -DVERBOSE_TIMER | ||||
							
								
								
									
										79
									
								
								EnhancedSolver/2D-mpi/dcavity.par
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								EnhancedSolver/2D-mpi/dcavity.par
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #============================================================================== | ||||
| #                              Driven Cavity | ||||
| #============================================================================== | ||||
|  | ||||
| # Problem specific Data: | ||||
| # --------------------- | ||||
|  | ||||
| name dcavity        # name of flow setup | ||||
|  | ||||
| bcTop      1			#  flags for boundary conditions | ||||
| bcBottom   1			#  1 = no-slip      3 = outflow | ||||
| bcLeft     1			#  2 = free-slip    4 = periodic | ||||
| bcRight    1			# | ||||
|  | ||||
| gx    0.0			# Body forces (e.g. gravity) | ||||
| gy    0.0			# | ||||
|  | ||||
| re    10.0		    # Reynolds number | ||||
|  | ||||
| u_init    1.0		# initial value for velocity in x-direction | ||||
| v_init    0.0		# initial value for velocity in y-direction | ||||
| p_init    0.0		# initial value for pressure | ||||
|  | ||||
| # Geometry Data: | ||||
| # ------------- | ||||
|  | ||||
| xlength    1.0		# domain size in x-direction | ||||
| ylength    1.0		# domain size in y-direction | ||||
| imax       128		# number of interior cells in x-direction | ||||
| jmax       128		# number of interior cells in y-direction | ||||
|  | ||||
| # Time Data: | ||||
| # --------- | ||||
|  | ||||
| te      10.0		# final time | ||||
| dt      0.02	    # time stepsize | ||||
| tau     0.5	    	# safety factor for time stepsize control (<0 constant delt) | ||||
|  | ||||
| # Pressure Iteration Data: | ||||
| # ----------------------- | ||||
|  | ||||
| itermax  1000		# maximal number of pressure iteration in one time step | ||||
| eps      0.001		# stopping tolerance for pressure iteration | ||||
| rho      0.5 | ||||
| omg      1.8		# relaxation parameter for SOR iteration | ||||
| gamma    0.9		# upwind differencing factor gamma | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        3         # Multigrid levels | ||||
| presmooth     10        # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|  | ||||
| numberOfParticles   200 | ||||
| startTime           2.0 | ||||
| injectTimePeriod    0.5 | ||||
| writeTimePeriod     0.2 | ||||
|  | ||||
| x1                  0.1 | ||||
| y1                  0.9 | ||||
| x2                  0.9 | ||||
| y2                  0.9 | ||||
|  | ||||
|  | ||||
| # Obstacle Geometry Data: | ||||
| # ----------------------- | ||||
| # Shape 0 disable, 1 Rectangle/Square, 2 Circle | ||||
|  | ||||
| shape               0  | ||||
| xCenter             0.5 | ||||
| yCenter             0.5 | ||||
| xRectLength         0.5 | ||||
| yRectLength         0.5 | ||||
| circleRadius        0.5 | ||||
| #=============================================================================== | ||||
							
								
								
									
										21
									
								
								EnhancedSolver/2D-mpi/include_CLANG.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								EnhancedSolver/2D-mpi/include_CLANG.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| ifeq ($(ENABLE_MPI),true) | ||||
| CC   = mpicc | ||||
| DEFINES  = -D_MPI | ||||
| else | ||||
| CC   = cc | ||||
| endif | ||||
|  | ||||
| GCC  = cc | ||||
| LINKER = $(CC) | ||||
|  | ||||
| ifeq ($(ENABLE_OPENMP),true) | ||||
| OPENMP   = -fopenmp | ||||
| #OPENMP   = -Xpreprocessor -fopenmp #required on Macos with homebrew libomp | ||||
| LIBS     = # -lomp | ||||
| endif | ||||
|  | ||||
| VERSION  = --version | ||||
| CFLAGS   = -Ofast -std=c17 | ||||
| LFLAGS   = $(OPENMP) -lm | ||||
| DEFINES  += -D_GNU_SOURCE# -DDEBUG | ||||
| INCLUDES = -I/opt/homebrew/include | ||||
							
								
								
									
										20
									
								
								EnhancedSolver/2D-mpi/include_GCC.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								EnhancedSolver/2D-mpi/include_GCC.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| ifeq ($(ENABLE_MPI),true) | ||||
| CC   = mpicc | ||||
| DEFINES  = -D_MPI | ||||
| else | ||||
| CC   = gcc | ||||
| endif | ||||
|  | ||||
| GCC  = gcc | ||||
| LINKER = $(CC) | ||||
|  | ||||
| ifeq ($(ENABLE_OPENMP),true) | ||||
| OPENMP   = -fopenmp | ||||
| endif | ||||
|  | ||||
| VERSION  = --version | ||||
| CFLAGS   = -Ofast -ffreestanding -std=c99 $(OPENMP) | ||||
| LFLAGS   = $(OPENMP) | ||||
| DEFINES  += -D_GNU_SOURCE | ||||
| INCLUDES = | ||||
| LIBS     = | ||||
							
								
								
									
										20
									
								
								EnhancedSolver/2D-mpi/include_ICC.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								EnhancedSolver/2D-mpi/include_ICC.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| ifeq ($(ENABLE_MPI),true) | ||||
| CC   = mpiicc | ||||
| DEFINES  = -D_MPI | ||||
| else | ||||
| CC = icc | ||||
| endif | ||||
|  | ||||
| GCC  = gcc | ||||
| LINKER = $(CC) | ||||
|  | ||||
| ifeq ($(ENABLE_OPENMP),true) | ||||
| OPENMP   = -qopenmp | ||||
| endif | ||||
|  | ||||
| VERSION  = --version | ||||
| CFLAGS   =  -O3 -xHost -qopt-zmm-usage=high -std=c99 $(OPENMP) | ||||
| LFLAGS   = $(OPENMP) | ||||
| DEFINES  += -D_GNU_SOURCE# -DDEBUG | ||||
| INCLUDES = | ||||
| LIBS     = | ||||
							
								
								
									
										79
									
								
								EnhancedSolver/2D-mpi/karman.par
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								EnhancedSolver/2D-mpi/karman.par
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #============================================================================== | ||||
| #                            Laminar Canal Flow | ||||
| #============================================================================== | ||||
|  | ||||
| # Problem specific Data: | ||||
| # --------------------- | ||||
|  | ||||
| name karman             # name of flow setup | ||||
|  | ||||
| bcTop      1			#  flags for boundary conditions | ||||
| bcBottom   1			#  1 = no-slip      3 = outflow | ||||
| bcLeft     3			#  2 = free-slip    4 = periodic | ||||
| bcRight    3			# | ||||
|  | ||||
| gx    0.0      # Body forces (e.g. gravity) | ||||
| gy    0.0      # | ||||
|  | ||||
| re    5050.0	   # Reynolds number | ||||
|  | ||||
| u_init    1.0      # initial value for velocity in x-direction | ||||
| v_init    0.0      # initial value for velocity in y-direction | ||||
| p_init    0.0      # initial value for pressure | ||||
|  | ||||
| # Geometry Data: | ||||
| # ------------- | ||||
|  | ||||
| xlength    30.0     # domain size in x-direction | ||||
| ylength    8.0	   # domain size in y-direction | ||||
| imax       400      # number of interior cells in x-direction | ||||
| jmax       200	   # number of interior cells in y-direction | ||||
|  | ||||
| # Time Data: | ||||
| # --------- | ||||
|  | ||||
| te      150.0   # final time | ||||
| dt      0.02    # time stepsize | ||||
| tau     0.5     # safety factor for time stepsize control (<0 constant delt) | ||||
|  | ||||
| # Pressure Iteration Data: | ||||
| # ----------------------- | ||||
|  | ||||
| itermax  200       # maximal number of pressure iteration in one time step | ||||
| eps      0.001   # stopping tolerance for pressure iteration | ||||
| rho      0.52 | ||||
| omg      1.75      # relaxation parameter for SOR iteration | ||||
| gamma    0.9       # upwind differencing factor gamma | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        3         # Multigrid levels | ||||
| presmooth     15         # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|  | ||||
| numberOfParticles   200 | ||||
| startTime           50 | ||||
| injectTimePeriod    1.0 | ||||
| writeTimePeriod     0.5 | ||||
|  | ||||
| x1                  0.0 | ||||
| y1                  3.8 | ||||
| x2                  0.0 | ||||
| y2                  4.1 | ||||
|  | ||||
| # Obstacle Geometry Data: | ||||
| # ----------------------- | ||||
| # Shape 0 disable, 1 Rectangle/Square, 2 Circle | ||||
|  | ||||
| shape               2  | ||||
| xCenter             5.0 | ||||
| yCenter             4.0 | ||||
| xRectLength         2.0 | ||||
| yRectLength         1.0 | ||||
| circleRadius        1.0 | ||||
|  | ||||
| #=============================================================================== | ||||
							
								
								
									
										61
									
								
								EnhancedSolver/2D-mpi/src/affinity.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								EnhancedSolver/2D-mpi/src/affinity.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifdef __linux__ | ||||
| #ifdef _OPENMP | ||||
| #include <pthread.h> | ||||
| #include <sched.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/syscall.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #define MAX_NUM_THREADS 128 | ||||
| #define gettid()        syscall(SYS_gettid) | ||||
|  | ||||
| static int getProcessorID(cpu_set_t* cpu_set) | ||||
| { | ||||
|     int processorId; | ||||
|  | ||||
|     for (processorId = 0; processorId < MAX_NUM_THREADS; processorId++) { | ||||
|         if (CPU_ISSET(processorId, cpu_set)) { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return processorId; | ||||
| } | ||||
|  | ||||
| int affinity_getProcessorId() | ||||
| { | ||||
|     cpu_set_t cpu_set; | ||||
|     CPU_ZERO(&cpu_set); | ||||
|     sched_getaffinity(gettid(), sizeof(cpu_set_t), &cpu_set); | ||||
|  | ||||
|     return getProcessorID(&cpu_set); | ||||
| } | ||||
|  | ||||
| void affinity_pinThread(int processorId) | ||||
| { | ||||
|     cpu_set_t cpuset; | ||||
|     pthread_t thread; | ||||
|  | ||||
|     thread = pthread_self(); | ||||
|     CPU_ZERO(&cpuset); | ||||
|     CPU_SET(processorId, &cpuset); | ||||
|     pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); | ||||
| } | ||||
|  | ||||
| void affinity_pinProcess(int processorId) | ||||
| { | ||||
|     cpu_set_t cpuset; | ||||
|  | ||||
|     CPU_ZERO(&cpuset); | ||||
|     CPU_SET(processorId, &cpuset); | ||||
|     sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); | ||||
| } | ||||
| #endif /*_OPENMP*/ | ||||
| #endif /*__linux__*/ | ||||
							
								
								
									
										14
									
								
								EnhancedSolver/2D-mpi/src/affinity.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								EnhancedSolver/2D-mpi/src/affinity.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef AFFINITY_H | ||||
| #define AFFINITY_H | ||||
|  | ||||
| extern int affinity_getProcessorId(); | ||||
| extern void affinity_pinProcess(int); | ||||
| extern void affinity_pinThread(int); | ||||
|  | ||||
| #endif /*AFFINITY_H*/ | ||||
							
								
								
									
										38
									
								
								EnhancedSolver/2D-mpi/src/allocate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								EnhancedSolver/2D-mpi/src/allocate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <errno.h> | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "allocate.h" | ||||
|  | ||||
| void* allocate(size_t alignment, size_t bytesize) | ||||
| { | ||||
|     int errorCode; | ||||
|     void* ptr; | ||||
|  | ||||
|     errorCode = posix_memalign(&ptr, alignment, bytesize); | ||||
|  | ||||
|     if (errorCode) { | ||||
|         if (errorCode == EINVAL) { | ||||
|             fprintf(stderr, "Error: Alignment parameter is not a power of two\n"); | ||||
|             exit(EXIT_FAILURE); | ||||
|         } | ||||
|         if (errorCode == ENOMEM) { | ||||
|             fprintf(stderr, "Error: Insufficient memory to fulfill the request\n"); | ||||
|             exit(EXIT_FAILURE); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (ptr == NULL) { | ||||
|         fprintf(stderr, "Error: posix_memalign failed!\n"); | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
|  | ||||
|     return ptr; | ||||
| } | ||||
							
								
								
									
										13
									
								
								EnhancedSolver/2D-mpi/src/allocate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								EnhancedSolver/2D-mpi/src/allocate.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __ALLOCATE_H_ | ||||
| #define __ALLOCATE_H_ | ||||
| #include <stdlib.h> | ||||
|  | ||||
| extern void* allocate(size_t alignment, size_t bytesize); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										204
									
								
								EnhancedSolver/2D-mpi/src/comm-v1.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								EnhancedSolver/2D-mpi/src/comm-v1.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | ||||
| /* | ||||
|  * Copyright (C) NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "comm.h" | ||||
|  | ||||
| #ifdef _MPI | ||||
| // subroutines local to this module | ||||
| static int sum(int* sizes, int position) | ||||
| { | ||||
|     int sum = 0; | ||||
|  | ||||
|     for (int i = 0; i < position; i++) { | ||||
|         sum += sizes[i]; | ||||
|     } | ||||
|  | ||||
|     return sum; | ||||
| } | ||||
|  | ||||
| static void gatherArray( | ||||
|     Comm* c, int cnt, int* rcvCounts, int* displs, double* src, double* dst) | ||||
| { | ||||
|     double* sendbuffer = src + (c->imaxLocal + 2); | ||||
|  | ||||
|     if (c->rank == 0) { | ||||
|         sendbuffer = src; | ||||
|     } | ||||
|  | ||||
|     MPI_Gatherv(sendbuffer, | ||||
|         cnt, | ||||
|         MPI_DOUBLE, | ||||
|         dst, | ||||
|         rcvCounts, | ||||
|         displs, | ||||
|         MPI_DOUBLE, | ||||
|         0, | ||||
|         MPI_COMM_WORLD); | ||||
| } | ||||
| #endif // defined _MPI | ||||
|  | ||||
| // exported subroutines | ||||
| int commIsBoundary(Comm* c, int direction) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     switch (direction) { | ||||
|     case L: | ||||
|         return 1; | ||||
|         break; | ||||
|     case R: | ||||
|         return 1; | ||||
|         break; | ||||
|     case B: | ||||
|         return c->rank == 0; | ||||
|         break; | ||||
|     case T: | ||||
|         return c->rank == (c->size - 1); | ||||
|         break; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| void commExchange(Comm* c, double* grid) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Request requests[4] = { MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL }; | ||||
|  | ||||
|     /* exchange ghost cells with top neighbor */ | ||||
|     if (c->rank + 1 < c->size) { | ||||
|         int top     = c->rank + 1; | ||||
|         double* src = grid + (c->jmaxLocal) * (c->imaxLocal + 2) + 1; | ||||
|         double* dst = grid + (c->jmaxLocal + 1) * (c->imaxLocal + 2) + 1; | ||||
|  | ||||
|         MPI_Isend(src, c->imaxLocal, MPI_DOUBLE, top, 1, MPI_COMM_WORLD, &requests[0]); | ||||
|         MPI_Irecv(dst, c->imaxLocal, MPI_DOUBLE, top, 2, MPI_COMM_WORLD, &requests[1]); | ||||
|     } | ||||
|  | ||||
|     /* exchange ghost cells with bottom neighbor */ | ||||
|     if (c->rank > 0) { | ||||
|         int bottom  = c->rank - 1; | ||||
|         double* src = grid + (c->imaxLocal + 2) + 1; | ||||
|         double* dst = grid + 1; | ||||
|  | ||||
|         MPI_Isend(src, c->imaxLocal, MPI_DOUBLE, bottom, 2, MPI_COMM_WORLD, &requests[2]); | ||||
|         MPI_Irecv(dst, c->imaxLocal, MPI_DOUBLE, bottom, 1, MPI_COMM_WORLD, &requests[3]); | ||||
|     } | ||||
|  | ||||
|     MPI_Waitall(4, requests, MPI_STATUSES_IGNORE); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commShift(Comm* c, double* f, double* g) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Request requests[2] = { MPI_REQUEST_NULL, MPI_REQUEST_NULL }; | ||||
|  | ||||
|     /* shift G */ | ||||
|     /* receive ghost cells from bottom neighbor */ | ||||
|     if (c->rank > 0) { | ||||
|         int bottom = c->rank - 1; | ||||
|         MPI_Irecv(g + 1, | ||||
|             c->imaxLocal, | ||||
|             MPI_DOUBLE, | ||||
|             bottom, | ||||
|             0, | ||||
|             MPI_COMM_WORLD, | ||||
|             &requests[0]); | ||||
|     } | ||||
|  | ||||
|     if (c->rank + 1 < c->size) { | ||||
|         int top     = c->rank + 1; | ||||
|         double* buf = g + (c->jmaxLocal) * (c->imaxLocal + 2) + 1; | ||||
|         /* send ghost cells to top neighbor */ | ||||
|         MPI_Isend(buf, c->imaxLocal, MPI_DOUBLE, top, 0, MPI_COMM_WORLD, &requests[1]); | ||||
|     } | ||||
|  | ||||
|     MPI_Waitall(2, requests, MPI_STATUSES_IGNORE); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commCollectResult(Comm* c, | ||||
|     double* ug, | ||||
|     double* vg, | ||||
|     double* pg, | ||||
|     double* u, | ||||
|     double* v, | ||||
|     double* p, | ||||
|     int jmax, | ||||
|     int imax) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     int *rcvCounts, *displs; | ||||
|     int cnt = c->jmaxLocal * (imax + 2); | ||||
|  | ||||
|     if (c->rank == 0) { | ||||
|         rcvCounts = (int*)malloc(c->size * sizeof(int)); | ||||
|         displs    = (int*)malloc(c->size * sizeof(int)); | ||||
|     } | ||||
|  | ||||
|     if (c->rank == 0 && c->size == 1) { | ||||
|         cnt = (c->jmaxLocal + 2) * (imax + 2); | ||||
|     } else if (c->rank == 0 || c->rank == (c->size - 1)) { | ||||
|         cnt = (c->jmaxLocal + 1) * (imax + 2); | ||||
|     } | ||||
|  | ||||
|     MPI_Gather(&cnt, 1, MPI_INTEGER, rcvCounts, 1, MPI_INTEGER, 0, MPI_COMM_WORLD); | ||||
|  | ||||
|     if (c->rank == 0) { | ||||
|         displs[0]  = 0; | ||||
|         int cursor = rcvCounts[0]; | ||||
|  | ||||
|         for (int i = 1; i < c->size; i++) { | ||||
|             displs[i] = cursor; | ||||
|             cursor += rcvCounts[i]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     gatherArray(c, cnt, rcvCounts, displs, p, pg); | ||||
|     gatherArray(c, cnt, rcvCounts, displs, u, ug); | ||||
|     gatherArray(c, cnt, rcvCounts, displs, v, vg); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commPartition(Comm* c, int jmax, int imax) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     c->imaxLocal = imax; | ||||
|     c->jmaxLocal = sizeOfRank(c->coords[JDIM], c->size, jmax); | ||||
| #else | ||||
|     c->imaxLocal = imax; | ||||
|     c->jmaxLocal = jmax; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commUpdateDatatypes(Comm* oldcomm, Comm* newcomm, int imaxLocal, int jmaxLocal) | ||||
| { | ||||
|     Comm* newcomm; | ||||
|  | ||||
| #if defined _MPI | ||||
|     newcomm->comm = MPI_COMM_NULL; | ||||
|     int result    = MPI_Comm_dup(oldcomm->comm, &newcomm->comm); | ||||
|  | ||||
|     if (result == MPI_ERR_COMM) { | ||||
|         printf("\nNull communicator. Duplication failed !!\n"); | ||||
|     } | ||||
| #endif | ||||
|     newcomm->imaxLocal = imaxLocal; | ||||
|     newcomm->jmaxLocal = jmaxLocal; | ||||
| } | ||||
|  | ||||
| void commFreeCommunicator(Comm* comm) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Comm_free(&comm->comm); | ||||
| #endif | ||||
| } | ||||
							
								
								
									
										335
									
								
								EnhancedSolver/2D-mpi/src/comm-v2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								EnhancedSolver/2D-mpi/src/comm-v2.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,335 @@ | ||||
| /* | ||||
|  * Copyright (C) NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "comm.h" | ||||
|  | ||||
| #ifdef _MPI | ||||
| // subroutines local to this module | ||||
| static int sum(int* sizes, int position) | ||||
| { | ||||
|     int sum = 0; | ||||
|  | ||||
|     for (int i = 0; i < position; i++) { | ||||
|         sum += sizes[i]; | ||||
|     } | ||||
|  | ||||
|     return sum; | ||||
| } | ||||
|  | ||||
| static void assembleResult(Comm* c, double* src, double* dst, int imax, int jmax) | ||||
| { | ||||
|     MPI_Request* requests; | ||||
|     int numRequests = 1; | ||||
|  | ||||
|     if (c->rank == 0) { | ||||
|         numRequests = c->size + 1; | ||||
|     } else { | ||||
|         numRequests = 1; | ||||
|     } | ||||
|  | ||||
|     requests = (MPI_Request*)malloc(numRequests * sizeof(MPI_Request)); | ||||
|  | ||||
|     /* all ranks send their bulk array, including the external boundary layer */ | ||||
|     MPI_Datatype bulkType; | ||||
|     int oldSizes[NDIMS] = { c->jmaxLocal + 2, c->imaxLocal + 2 }; | ||||
|     int newSizes[NDIMS] = { c->jmaxLocal, c->imaxLocal }; | ||||
|     int starts[NDIMS]   = { 1, 1 }; | ||||
|  | ||||
|     if (commIsBoundary(c, L)) { | ||||
|         newSizes[CIDIM] += 1; | ||||
|         starts[CIDIM] = 0; | ||||
|     } | ||||
|     if (commIsBoundary(c, R)) { | ||||
|         newSizes[CIDIM] += 1; | ||||
|     } | ||||
|     if (commIsBoundary(c, B)) { | ||||
|         newSizes[CJDIM] += 1; | ||||
|         starts[CJDIM] = 0; | ||||
|     } | ||||
|     if (commIsBoundary(c, T)) { | ||||
|         newSizes[CJDIM] += 1; | ||||
|     } | ||||
|  | ||||
|     MPI_Type_create_subarray(NDIMS, | ||||
|         oldSizes, | ||||
|         newSizes, | ||||
|         starts, | ||||
|         MPI_ORDER_C, | ||||
|         MPI_DOUBLE, | ||||
|         &bulkType); | ||||
|     MPI_Type_commit(&bulkType); | ||||
|     MPI_Isend(src, 1, bulkType, 0, 0, c->comm, &requests[0]); | ||||
|  | ||||
|     int newSizesI[c->size]; | ||||
|     int newSizesJ[c->size]; | ||||
|     MPI_Gather(&newSizes[CIDIM], 1, MPI_INT, newSizesI, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||||
|     MPI_Gather(&newSizes[CJDIM], 1, MPI_INT, newSizesJ, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||||
|  | ||||
|     /* rank 0 assembles the subdomains */ | ||||
|     if (c->rank == 0) { | ||||
|         for (int i = 0; i < c->size; i++) { | ||||
|             MPI_Datatype domainType; | ||||
|             int oldSizes[NDIMS] = { jmax + 2, imax + 2 }; | ||||
|             int newSizes[NDIMS] = { newSizesJ[i], newSizesI[i] }; | ||||
|             int coords[NDIMS]; | ||||
|             MPI_Cart_coords(c->comm, i, NDIMS, coords); | ||||
|             int starts[NDIMS] = { sum(newSizesJ, coords[JDIM]), | ||||
|                 sum(newSizesI, coords[IDIM]) }; | ||||
|             printf( | ||||
|                 "Rank: %d, Coords(i,j): %d %d, Size(i,j): %d %d, Target Size(i,j): %d %d " | ||||
|                 "Starts(i,j): %d %d\n", | ||||
|                 i, | ||||
|                 coords[IDIM], | ||||
|                 coords[JDIM], | ||||
|                 oldSizes[CIDIM], | ||||
|                 oldSizes[CJDIM], | ||||
|                 newSizes[CIDIM], | ||||
|                 newSizes[CJDIM], | ||||
|                 starts[CIDIM], | ||||
|                 starts[CJDIM]); | ||||
|  | ||||
|             MPI_Type_create_subarray(NDIMS, | ||||
|                 oldSizes, | ||||
|                 newSizes, | ||||
|                 starts, | ||||
|                 MPI_ORDER_C, | ||||
|                 MPI_DOUBLE, | ||||
|                 &domainType); | ||||
|             MPI_Type_commit(&domainType); | ||||
|  | ||||
|             MPI_Irecv(dst, 1, domainType, i, 0, c->comm, &requests[i + 1]); | ||||
|             MPI_Type_free(&domainType); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     MPI_Waitall(numRequests, requests, MPI_STATUSES_IGNORE); | ||||
| } | ||||
| #endif // defined _MPI | ||||
|  | ||||
| // exported subroutines | ||||
| int commIsBoundary(Comm* c, int direction) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     switch (direction) { | ||||
|     case L: | ||||
|         return c->coords[IDIM] == 0; | ||||
|         break; | ||||
|     case R: | ||||
|         return c->coords[IDIM] == (c->dims[IDIM] - 1); | ||||
|         break; | ||||
|     case B: | ||||
|         return c->coords[JDIM] == 0; | ||||
|         break; | ||||
|     case T: | ||||
|         return c->coords[JDIM] == (c->dims[JDIM] - 1); | ||||
|         break; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| void commExchange(Comm* c, double* grid) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Request requests[8]; | ||||
|     for (int i = 0; i < 8; i++) | ||||
|         requests[i] = MPI_REQUEST_NULL; | ||||
|  | ||||
|     for (int i = 0; i < NDIRS; i++) { | ||||
|         double* sbuf = grid + c->sdispls[i]; | ||||
|         double* rbuf = grid + c->rdispls[i]; | ||||
|  | ||||
|         int tag = 0; | ||||
|         if (c->neighbours[i] != MPI_PROC_NULL) { | ||||
|             // printf("DEBUG: Rank %d - SendRecv with %d\n", c->rank, c->neighbours[i]); | ||||
|             tag = c->neighbours[i]; | ||||
|         } | ||||
|         MPI_Irecv(rbuf, | ||||
|             1, | ||||
|             c->bufferTypes[i], | ||||
|             c->neighbours[i], | ||||
|             tag, | ||||
|             c->comm, | ||||
|             &requests[i * 2]); | ||||
|         MPI_Isend(sbuf, | ||||
|             1, | ||||
|             c->bufferTypes[i], | ||||
|             c->neighbours[i], | ||||
|             c->rank, | ||||
|             c->comm, | ||||
|             &requests[i * 2 + 1]); | ||||
|     } | ||||
|  | ||||
|     MPI_Waitall(8, requests, MPI_STATUSES_IGNORE); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commShift(Comm* c, double* f, double* g) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Request requests[4] = { MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL }; | ||||
|  | ||||
|     /* shift G */ | ||||
|     /* receive ghost cells from bottom neighbor */ | ||||
|     double* buf = g + 1; | ||||
|     MPI_Irecv(buf, | ||||
|         1, | ||||
|         c->bufferTypes[B], | ||||
|         c->neighbours[B], | ||||
|         0, | ||||
|         c->comm, | ||||
|         &requests[0]); | ||||
|  | ||||
|     /* send ghost cells to top neighbor */ | ||||
|     buf = g + (c->jmaxLocal) * (c->imaxLocal + 2) + 1; | ||||
|     MPI_Isend(buf, 1, c->bufferTypes[T], c->neighbours[T], 0, c->comm, &requests[1]); | ||||
|  | ||||
|     /* shift F */ | ||||
|     /* receive ghost cells from left neighbor */ | ||||
|     buf = f + (c->imaxLocal + 2); | ||||
|     MPI_Irecv(buf, | ||||
|         1, | ||||
|         c->bufferTypes[L], | ||||
|         c->neighbours[L], | ||||
|         1, | ||||
|         c->comm, | ||||
|         &requests[2]); | ||||
|  | ||||
|     /* send ghost cells to right neighbor */ | ||||
|     buf = f + (c->imaxLocal + 2) + (c->imaxLocal); | ||||
|     MPI_Isend(buf, | ||||
|         1, | ||||
|         c->bufferTypes[R], | ||||
|         c->neighbours[R], | ||||
|         1, | ||||
|         c->comm, | ||||
|         &requests[3]); | ||||
|  | ||||
|     MPI_Waitall(4, requests, MPI_STATUSES_IGNORE); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commCollectResult(Comm* c, | ||||
|     double* ug, | ||||
|     double* vg, | ||||
|     double* pg, | ||||
|     double* u, | ||||
|     double* v, | ||||
|     double* p, | ||||
|     int imax, | ||||
|     int jmax) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     /* collect P */ | ||||
|     assembleResult(c, p, pg, imax, jmax); | ||||
|  | ||||
|     /* collect U */ | ||||
|     assembleResult(c, u, ug, imax, jmax); | ||||
|  | ||||
|     /* collect V */ | ||||
|     assembleResult(c, v, vg, imax, jmax); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commPartition(Comm* c, int jmax, int imax) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     int dims[NDIMS]    = { 0, 0 }; | ||||
|     int periods[NDIMS] = { 0, 0 }; | ||||
|     MPI_Dims_create(c->size, NDIMS, dims); | ||||
|     MPI_Cart_create(MPI_COMM_WORLD, NDIMS, dims, periods, 0, &c->comm); | ||||
|     MPI_Cart_shift(c->comm, IDIM, 1, &c->neighbours[L], &c->neighbours[R]); | ||||
|     MPI_Cart_shift(c->comm, JDIM, 1, &c->neighbours[B], &c->neighbours[T]); | ||||
|     MPI_Cart_get(c->comm, NDIMS, c->dims, periods, c->coords); | ||||
|  | ||||
|     int imaxLocal = sizeOfRank(c->coords[IDIM], dims[IDIM], imax); | ||||
|     int jmaxLocal = sizeOfRank(c->coords[JDIM], dims[JDIM], jmax); | ||||
|  | ||||
|     c->imaxLocal = imaxLocal; | ||||
|     c->jmaxLocal = jmaxLocal; | ||||
|  | ||||
|     MPI_Datatype jBufferType; | ||||
|     MPI_Type_contiguous(imaxLocal, MPI_DOUBLE, &jBufferType); | ||||
|     MPI_Type_commit(&jBufferType); | ||||
|  | ||||
|     MPI_Datatype iBufferType; | ||||
|     MPI_Type_vector(jmaxLocal, 1, imaxLocal + 2, MPI_DOUBLE, &iBufferType); | ||||
|     MPI_Type_commit(&iBufferType); | ||||
|  | ||||
|     c->bufferTypes[L]   = iBufferType; | ||||
|     c->bufferTypes[R]  = iBufferType; | ||||
|     c->bufferTypes[B] = jBufferType; | ||||
|     c->bufferTypes[T]    = jBufferType; | ||||
|  | ||||
|     c->sdispls[L]   = (imaxLocal + 2) + 1; | ||||
|     c->sdispls[R]  = (imaxLocal + 2) + imaxLocal; | ||||
|     c->sdispls[B] = (imaxLocal + 2) + 1; | ||||
|     c->sdispls[T]    = jmaxLocal * (imaxLocal + 2) + 1; | ||||
|  | ||||
|     c->rdispls[L]   = (imaxLocal + 2); | ||||
|     c->rdispls[R]  = (imaxLocal + 2) + (imaxLocal + 1); | ||||
|     c->rdispls[B] = 1; | ||||
|     c->rdispls[T]    = (jmaxLocal + 1) * (imaxLocal + 2) + 1; | ||||
| #else | ||||
|     c->imaxLocal = imax; | ||||
|     c->jmaxLocal = jmax; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commUpdateDatatypes(Comm* oldcomm, Comm* newcomm, int imaxLocal, int jmaxLocal) | ||||
| { | ||||
| #if defined _MPI | ||||
|     newcomm->comm = MPI_COMM_NULL; | ||||
|     int result = MPI_Comm_dup(oldcomm->comm, &newcomm->comm); | ||||
|  | ||||
|     if (result == MPI_ERR_COMM) { | ||||
|         printf("\nNull communicator. Duplication failed !!\n"); | ||||
|     } | ||||
|      | ||||
|     newcomm->imaxLocal = imaxLocal; | ||||
|     newcomm->jmaxLocal = jmaxLocal; | ||||
|  | ||||
|     MPI_Datatype jBufferType; | ||||
|     MPI_Type_contiguous(imaxLocal, MPI_DOUBLE, &jBufferType); | ||||
|     MPI_Type_commit(&jBufferType); | ||||
|  | ||||
|     MPI_Datatype iBufferType; | ||||
|     MPI_Type_vector(jmaxLocal, 1, imaxLocal + 2, MPI_DOUBLE, &iBufferType); | ||||
|     MPI_Type_commit(&iBufferType); | ||||
|  | ||||
|     newcomm->bufferTypes[L]   = iBufferType; | ||||
|     newcomm->bufferTypes[R]  = iBufferType; | ||||
|     newcomm->bufferTypes[B] = jBufferType; | ||||
|     newcomm->bufferTypes[T]    = jBufferType; | ||||
|  | ||||
|     newcomm->sdispls[L]   = (imaxLocal + 2) + 1; | ||||
|     newcomm->sdispls[R]  = (imaxLocal + 2) + imaxLocal; | ||||
|     newcomm->sdispls[B] = (imaxLocal + 2) + 1; | ||||
|     newcomm->sdispls[T]    = jmaxLocal * (imaxLocal + 2) + 1; | ||||
|  | ||||
|     newcomm->rdispls[L]   = (imaxLocal + 2); | ||||
|     newcomm->rdispls[R]  = (imaxLocal + 2) + (imaxLocal + 1); | ||||
|     newcomm->rdispls[B] = 1; | ||||
|     newcomm->rdispls[T]    = (jmaxLocal + 1) * (imaxLocal + 2) + 1; | ||||
| #else | ||||
|     newcomm->imaxLocal = imaxLocal; | ||||
|     newcomm->jmaxLocal = jmaxLocal; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commFreeCommunicator(Comm* comm) | ||||
| { | ||||
|     #ifdef _MPI | ||||
|         MPI_Comm_free(&comm->comm); | ||||
|     #endif | ||||
| } | ||||
							
								
								
									
										316
									
								
								EnhancedSolver/2D-mpi/src/comm-v3.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								EnhancedSolver/2D-mpi/src/comm-v3.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,316 @@ | ||||
| /* | ||||
|  * Copyright (C) NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "comm.h" | ||||
|  | ||||
| #ifdef _MPI | ||||
| // subroutines local to this module | ||||
| static int sum(int* sizes, int position) | ||||
| { | ||||
|     int sum = 0; | ||||
|  | ||||
|     for (int i = 0; i < position; i++) { | ||||
|         sum += sizes[i]; | ||||
|     } | ||||
|  | ||||
|     return sum; | ||||
| } | ||||
|  | ||||
| static void assembleResult(Comm* c, double* src, double* dst, int imax, int jmax) | ||||
| { | ||||
|     MPI_Request* requests; | ||||
|     int numRequests = 1; | ||||
|  | ||||
|     if (c->rank == 0) { | ||||
|         numRequests = c->size + 1; | ||||
|     } else { | ||||
|         numRequests = 1; | ||||
|     } | ||||
|  | ||||
|     requests = (MPI_Request*)malloc(numRequests * sizeof(MPI_Request)); | ||||
|  | ||||
|     /* all ranks send their bulk array, including the external boundary layer */ | ||||
|     MPI_Datatype bulkType; | ||||
|     int oldSizes[NDIMS] = { c->jmaxLocal + 2, c->imaxLocal + 2 }; | ||||
|     int newSizes[NDIMS] = { c->jmaxLocal, c->imaxLocal }; | ||||
|     int starts[NDIMS]   = { 1, 1 }; | ||||
|  | ||||
|     if (commIsBoundary(c, L)) { | ||||
|         newSizes[CIDIM] += 1; | ||||
|         starts[CIDIM] = 0; | ||||
|     } | ||||
|     if (commIsBoundary(c, R)) { | ||||
|         newSizes[CIDIM] += 1; | ||||
|     } | ||||
|     if (commIsBoundary(c, B)) { | ||||
|         newSizes[CJDIM] += 1; | ||||
|         starts[CJDIM] = 0; | ||||
|     } | ||||
|     if (commIsBoundary(c, T)) { | ||||
|         newSizes[CJDIM] += 1; | ||||
|     } | ||||
|  | ||||
|     MPI_Type_create_subarray(NDIMS, | ||||
|         oldSizes, | ||||
|         newSizes, | ||||
|         starts, | ||||
|         MPI_ORDER_C, | ||||
|         MPI_DOUBLE, | ||||
|         &bulkType); | ||||
|     MPI_Type_commit(&bulkType); | ||||
|     MPI_Isend(src, 1, bulkType, 0, 0, c->comm, &requests[0]); | ||||
|  | ||||
|     int newSizesI[c->size]; | ||||
|     int newSizesJ[c->size]; | ||||
|     MPI_Gather(&newSizes[CIDIM], 1, MPI_INT, newSizesI, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||||
|     MPI_Gather(&newSizes[CJDIM], 1, MPI_INT, newSizesJ, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||||
|  | ||||
|     /* rank 0 assembles the subdomains */ | ||||
|     if (c->rank == 0) { | ||||
|         for (int i = 0; i < c->size; i++) { | ||||
|             MPI_Datatype domainType; | ||||
|             int oldSizes[NDIMS] = { jmax + 2, imax + 2 }; | ||||
|             int newSizes[NDIMS] = { newSizesJ[i], newSizesI[i] }; | ||||
|             int coords[NDIMS]; | ||||
|             MPI_Cart_coords(c->comm, i, NDIMS, coords); | ||||
|             int starts[NDIMS] = { sum(newSizesJ, coords[JDIM]), | ||||
|                 sum(newSizesI, coords[IDIM]) }; | ||||
|             printf( | ||||
|                 "Rank: %d, Coords(i,j): %d %d, Size(i,j): %d %d, Target Size(i,j): %d %d " | ||||
|                 "Starts(i,j): %d %d\n", | ||||
|                 i, | ||||
|                 coords[IDIM], | ||||
|                 coords[JDIM], | ||||
|                 oldSizes[CIDIM], | ||||
|                 oldSizes[CJDIM], | ||||
|                 newSizes[CIDIM], | ||||
|                 newSizes[CJDIM], | ||||
|                 starts[CIDIM], | ||||
|                 starts[CJDIM]); | ||||
|  | ||||
|             MPI_Type_create_subarray(NDIMS, | ||||
|                 oldSizes, | ||||
|                 newSizes, | ||||
|                 starts, | ||||
|                 MPI_ORDER_C, | ||||
|                 MPI_DOUBLE, | ||||
|                 &domainType); | ||||
|             MPI_Type_commit(&domainType); | ||||
|  | ||||
|             MPI_Irecv(dst, 1, domainType, i, 0, c->comm, &requests[i + 1]); | ||||
|             MPI_Type_free(&domainType); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     MPI_Waitall(numRequests, requests, MPI_STATUSES_IGNORE); | ||||
| } | ||||
| #endif // defined _MPI | ||||
|  | ||||
| // exported subroutines | ||||
| int commIsBoundary(Comm* c, int direction) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     switch (direction) { | ||||
|     case L: | ||||
|         return c->coords[IDIM] == 0; | ||||
|         break; | ||||
|     case R: | ||||
|         return c->coords[IDIM] == (c->dims[IDIM] - 1); | ||||
|         break; | ||||
|     case B: | ||||
|         return c->coords[JDIM] == 0; | ||||
|         break; | ||||
|     case T: | ||||
|         return c->coords[JDIM] == (c->dims[JDIM] - 1); | ||||
|         break; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| void commExchange(Comm* c, double* grid) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     int counts[NDIRS] = { 1, 1, 1, 1 }; | ||||
|     MPI_Neighbor_alltoallw(grid, | ||||
|         counts, | ||||
|         c->sdispls, | ||||
|         c->bufferTypes, | ||||
|         grid, | ||||
|         counts, | ||||
|         c->rdispls, | ||||
|         c->bufferTypes, | ||||
|         c->comm); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commShift(Comm* c, double* f, double* g) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Request requests[4] = { MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL, | ||||
|         MPI_REQUEST_NULL }; | ||||
|  | ||||
|     /* shift G */ | ||||
|     /* receive ghost cells from bottom neighbor */ | ||||
|     double* buf = g + 1; | ||||
|     MPI_Irecv(buf, | ||||
|         1, | ||||
|         c->bufferTypes[B], | ||||
|         c->neighbours[B], | ||||
|         0, | ||||
|         c->comm, | ||||
|         &requests[0]); | ||||
|  | ||||
|     /* send ghost cells to top neighbor */ | ||||
|     buf = g + (c->jmaxLocal) * (c->imaxLocal + 2) + 1; | ||||
|     MPI_Isend(buf, 1, c->bufferTypes[T], c->neighbours[T], 0, c->comm, &requests[1]); | ||||
|  | ||||
|     /* shift F */ | ||||
|     /* receive ghost cells from left neighbor */ | ||||
|     buf = f + (c->imaxLocal + 2); | ||||
|     MPI_Irecv(buf, | ||||
|         1, | ||||
|         c->bufferTypes[L], | ||||
|         c->neighbours[L], | ||||
|         1, | ||||
|         c->comm, | ||||
|         &requests[2]); | ||||
|  | ||||
|     /* send ghost cells to right neighbor */ | ||||
|     buf = f + (c->imaxLocal + 2) + (c->imaxLocal); | ||||
|     MPI_Isend(buf, | ||||
|         1, | ||||
|         c->bufferTypes[R], | ||||
|         c->neighbours[R], | ||||
|         1, | ||||
|         c->comm, | ||||
|         &requests[3]); | ||||
|  | ||||
|     MPI_Waitall(4, requests, MPI_STATUSES_IGNORE); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commCollectResult(Comm* c, | ||||
|     double* ug, | ||||
|     double* vg, | ||||
|     double* pg, | ||||
|     double* u, | ||||
|     double* v, | ||||
|     double* p, | ||||
|     int imax, | ||||
|     int jmax) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     /* collect P */ | ||||
|     assembleResult(c, p, pg, imax, jmax); | ||||
|  | ||||
|     /* collect U */ | ||||
|     assembleResult(c, u, ug, imax, jmax); | ||||
|  | ||||
|     /* collect V */ | ||||
|     assembleResult(c, v, vg, imax, jmax); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commPartition(Comm* c, int jmax, int imax) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     int dims[NDIMS]    = { 0, 0 }; | ||||
|     int periods[NDIMS] = { 0, 0 }; | ||||
|     MPI_Dims_create(c->size, NDIMS, dims); | ||||
|     MPI_Cart_create(MPI_COMM_WORLD, NDIMS, dims, periods, 0, &c->comm); | ||||
|     MPI_Cart_shift(c->comm, IDIM, 1, &c->neighbours[L], &c->neighbours[R]); | ||||
|     MPI_Cart_shift(c->comm, JDIM, 1, &c->neighbours[B], &c->neighbours[T]); | ||||
|     MPI_Cart_get(c->comm, NDIMS, c->dims, periods, c->coords); | ||||
|  | ||||
|     int imaxLocal = sizeOfRank(c->coords[IDIM], dims[IDIM], imax); | ||||
|     int jmaxLocal = sizeOfRank(c->coords[JDIM], dims[JDIM], jmax); | ||||
|  | ||||
|     c->imaxLocal = imaxLocal; | ||||
|     c->jmaxLocal = jmaxLocal; | ||||
|  | ||||
|     MPI_Datatype jBufferType; | ||||
|     MPI_Type_contiguous(imaxLocal, MPI_DOUBLE, &jBufferType); | ||||
|     MPI_Type_commit(&jBufferType); | ||||
|  | ||||
|     MPI_Datatype iBufferType; | ||||
|     MPI_Type_vector(jmaxLocal, 1, imaxLocal + 2, MPI_DOUBLE, &iBufferType); | ||||
|     MPI_Type_commit(&iBufferType); | ||||
|  | ||||
|     c->bufferTypes[L]   = iBufferType; | ||||
|     c->bufferTypes[R]  = iBufferType; | ||||
|     c->bufferTypes[B] = jBufferType; | ||||
|     c->bufferTypes[T]    = jBufferType; | ||||
|  | ||||
|     size_t dblsize     = sizeof(double); | ||||
|     c->sdispls[L]   = ((imaxLocal + 2) + 1) * dblsize; | ||||
|     c->sdispls[R]  = ((imaxLocal + 2) + imaxLocal) * dblsize; | ||||
|     c->sdispls[B] = ((imaxLocal + 2) + 1) * dblsize; | ||||
|     c->sdispls[T]    = (jmaxLocal * (imaxLocal + 2) + 1) * dblsize; | ||||
|  | ||||
|     c->rdispls[L]   = (imaxLocal + 2) * dblsize; | ||||
|     c->rdispls[R]  = ((imaxLocal + 2) + (imaxLocal + 1)) * dblsize; | ||||
|     c->rdispls[B] = 1 * dblsize; | ||||
|     c->rdispls[T]    = ((jmaxLocal + 1) * (imaxLocal + 2) + 1) * dblsize; | ||||
| #else | ||||
|     c->imaxLocal = imax; | ||||
|     c->jmaxLocal = jmax; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commUpdateDatatypes(Comm* oldcomm, Comm* newcomm, int imaxLocal, int jmaxLocal) | ||||
| { | ||||
| #if defined _MPI | ||||
|  | ||||
|     int result    = MPI_Comm_dup(oldcomm->comm, &newcomm->comm); | ||||
|  | ||||
|     if (result == MPI_ERR_COMM) { | ||||
|         printf("\nNull communicator. Duplication failed !!\n"); | ||||
|     } | ||||
|  | ||||
|     newcomm->imaxLocal = imaxLocal; | ||||
|     newcomm->jmaxLocal = jmaxLocal; | ||||
|  | ||||
|     MPI_Datatype jBufferType; | ||||
|     MPI_Type_contiguous(imaxLocal, MPI_DOUBLE, &jBufferType); | ||||
|     MPI_Type_commit(&jBufferType); | ||||
|  | ||||
|     MPI_Datatype iBufferType; | ||||
|     MPI_Type_vector(jmaxLocal, 1, imaxLocal + 2, MPI_DOUBLE, &iBufferType); | ||||
|     MPI_Type_commit(&iBufferType); | ||||
|  | ||||
|     newcomm->bufferTypes[L]   = iBufferType; | ||||
|     newcomm->bufferTypes[R]  = iBufferType; | ||||
|     newcomm->bufferTypes[B] = jBufferType; | ||||
|     newcomm->bufferTypes[T]    = jBufferType; | ||||
|  | ||||
|     newcomm->sdispls[L]   = (imaxLocal + 2) + 1; | ||||
|     newcomm->sdispls[R]  = (imaxLocal + 2) + imaxLocal; | ||||
|     newcomm->sdispls[B] = (imaxLocal + 2) + 1; | ||||
|     newcomm->sdispls[T]    = jmaxLocal * (imaxLocal + 2) + 1; | ||||
|  | ||||
|     newcomm->rdispls[L]   = (imaxLocal + 2); | ||||
|     newcomm->rdispls[R]  = (imaxLocal + 2) + (imaxLocal + 1); | ||||
|     newcomm->rdispls[B] = 1; | ||||
|     newcomm->rdispls[T]    = (jmaxLocal + 1) * (imaxLocal + 2) + 1; | ||||
| #else | ||||
|     newcomm->imaxLocal = imaxLocal; | ||||
|     newcomm->jmaxLocal = jmaxLocal; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commFreeCommunicator(Comm* comm) | ||||
| { | ||||
|     #ifdef _MPI | ||||
|         MPI_Comm_free(&comm->comm); | ||||
|     #endif | ||||
| } | ||||
							
								
								
									
										129
									
								
								EnhancedSolver/2D-mpi/src/comm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								EnhancedSolver/2D-mpi/src/comm.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "comm.h" | ||||
|  | ||||
| // subroutines local to this module | ||||
| int sizeOfRank(int rank, int size, int N) | ||||
| { | ||||
|     return N / size + ((N % size > rank) ? 1 : 0); | ||||
| } | ||||
|  | ||||
| void commReduction(double* v, int op) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     if (op == MAX) { | ||||
|         MPI_Allreduce(MPI_IN_PLACE, v, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); | ||||
|     } else if (op == SUM) { | ||||
|         MPI_Allreduce(MPI_IN_PLACE, v, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commPrintConfig(Comm* c) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     fflush(stdout); | ||||
|     MPI_Barrier(MPI_COMM_WORLD); | ||||
|     if (commIsMaster(c)) { | ||||
|         printf("Communication setup:\n"); | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < c->size; i++) { | ||||
|         if (i == c->rank) { | ||||
|             printf("\tRank %d of %d\n", c->rank, c->size); | ||||
|             printf("\tNeighbours (bottom, top, left, right): %d %d, %d, %d\n", | ||||
|                 c->neighbours[B], | ||||
|                 c->neighbours[T], | ||||
|                 c->neighbours[L], | ||||
|                 c->neighbours[R]); | ||||
|             printf("\tIs boundary:\n"); | ||||
|             printf("\t\tLEFT: %d\n", commIsBoundary(c, L)); | ||||
|             printf("\t\tRIGHT: %d\n", commIsBoundary(c, R)); | ||||
|             printf("\t\tBOTTOM: %d\n", commIsBoundary(c, B)); | ||||
|             printf("\t\tTOP: %d\n", commIsBoundary(c, T)); | ||||
|             printf("\tCoordinates (i,j) %d %d\n", c->coords[IDIM], c->coords[JDIM]); | ||||
|             printf("\tDims (i,j) %d %d\n", c->dims[IDIM], c->dims[JDIM]); | ||||
|             printf("\tLocal domain size (i,j) %dx%d\n", c->imaxLocal, c->jmaxLocal); | ||||
|             fflush(stdout); | ||||
|         } | ||||
|         MPI_Barrier(MPI_COMM_WORLD); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commInit(Comm* c, int argc, char** argv) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Init(&argc, &argv); | ||||
|     MPI_Comm_rank(MPI_COMM_WORLD, &(c->rank)); | ||||
|     MPI_Comm_size(MPI_COMM_WORLD, &(c->size)); | ||||
| #else | ||||
|     c->rank = 0; | ||||
|     c->size = 1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void commTestInit(Comm* c, double* p, double* f, double* g) | ||||
| { | ||||
|     int imax = c->imaxLocal; | ||||
|     int jmax = c->jmaxLocal; | ||||
|     int rank = c->rank; | ||||
|  | ||||
|     for (int j = 0; j < jmax + 2; j++) { | ||||
|         for (int i = 0; i < imax + 2; i++) { | ||||
|             p[j * (imax + 2) + i] = rank; | ||||
|             f[j * (imax + 2) + i] = rank; | ||||
|             g[j * (imax + 2) + i] = rank; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void testWriteFile(char* filename, double* grid, int imax, int jmax) | ||||
| { | ||||
|     FILE* fp = fopen(filename, "w"); | ||||
|  | ||||
|     if (fp == NULL) { | ||||
|         printf("Error!\n"); | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
|  | ||||
|     for (int j = 0; j < jmax + 2; j++) { | ||||
|         for (int i = 0; i < imax + 2; i++) { | ||||
|             fprintf(fp, "%.2f ", grid[j * (imax + 2) + i]); | ||||
|         } | ||||
|         fprintf(fp, "\n"); | ||||
|     } | ||||
|  | ||||
|     fclose(fp); | ||||
| } | ||||
|  | ||||
| void commTestWrite(Comm* c, double* p, double* f, double* g) | ||||
| { | ||||
|     int imax = c->imaxLocal; | ||||
|     int jmax = c->jmaxLocal; | ||||
|     int rank = c->rank; | ||||
|  | ||||
|     char filename[30]; | ||||
|     snprintf(filename, 30, "ptest-%d.dat", rank); | ||||
|     testWriteFile(filename, p, imax, jmax); | ||||
|  | ||||
|     snprintf(filename, 30, "ftest-%d.dat", rank); | ||||
|     testWriteFile(filename, f, imax, jmax); | ||||
|  | ||||
|     snprintf(filename, 30, "gtest-%d.dat", rank); | ||||
|     testWriteFile(filename, g, imax, jmax); | ||||
| } | ||||
|  | ||||
| void commFinalize(Comm* c) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     MPI_Finalize(); | ||||
| #endif | ||||
| } | ||||
							
								
								
									
										57
									
								
								EnhancedSolver/2D-mpi/src/comm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								EnhancedSolver/2D-mpi/src/comm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __COMM_H_ | ||||
| #define __COMM_H_ | ||||
| #if defined(_MPI) | ||||
| #include <mpi.h> | ||||
| #endif | ||||
|  | ||||
| enum direction { L = 0, R, B, T, NDIRS }; // L = Left, R = Right, B = Bottom, T =Top | ||||
| enum dimension { IDIM = 0, JDIM, NDIMS }; | ||||
| enum cdimension { CJDIM = 0, CIDIM }; | ||||
| enum layer { HALO = 0, BULK }; | ||||
| enum op { MAX = 0, SUM }; | ||||
|  | ||||
| typedef struct { | ||||
|     int rank; | ||||
|     int size; | ||||
| #if defined(_MPI) | ||||
|     MPI_Comm comm; | ||||
|     MPI_Datatype bufferTypes[NDIRS]; | ||||
|     MPI_Aint sdispls[NDIRS]; | ||||
|     MPI_Aint rdispls[NDIRS]; | ||||
| #endif | ||||
|     int neighbours[NDIRS]; | ||||
|     int coords[NDIMS], dims[NDIMS]; | ||||
|     int imaxLocal, jmaxLocal; | ||||
| } Comm; | ||||
|  | ||||
| extern int sizeOfRank(int rank, int size, int N); | ||||
| extern void commInit(Comm* c, int argc, char** argv); | ||||
| extern void commTestInit(Comm* c, double* p, double* f, double* g); | ||||
| extern void commTestWrite(Comm* c, double* p, double* f, double* g); | ||||
| extern void commFinalize(Comm* c); | ||||
| extern void commPartition(Comm* c, int jmax, int imax); | ||||
| extern void commPrintConfig(Comm*); | ||||
| extern void commExchange(Comm*, double*); | ||||
| extern void commShift(Comm* c, double* f, double* g); | ||||
| extern void commReduction(double* v, int op); | ||||
| extern int commIsBoundary(Comm* c, int direction); | ||||
| extern void commUpdateDatatypes(Comm*, Comm*, int, int); | ||||
| extern void commFreeCommunicator(Comm*); | ||||
| extern void commCollectResult(Comm* c, | ||||
|     double* ug, | ||||
|     double* vg, | ||||
|     double* pg, | ||||
|     double* u, | ||||
|     double* v, | ||||
|     double* p, | ||||
|     int jmax, | ||||
|     int imax); | ||||
|  | ||||
| static inline int commIsMaster(Comm* c) { return c->rank == 0; } | ||||
| #endif // __COMM_H_ | ||||
							
								
								
									
										718
									
								
								EnhancedSolver/2D-mpi/src/discretization.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										718
									
								
								EnhancedSolver/2D-mpi/src/discretization.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,718 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <float.h> | ||||
| #include <math.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "allocate.h" | ||||
| #include "comm.h" | ||||
| #include "discretization.h" | ||||
| #include "parameter.h" | ||||
| #include "util.h" | ||||
|  | ||||
| static double distance(double i, double j, double iCenter, double jCenter) | ||||
| { | ||||
|     return sqrt(pow(iCenter - i, 2) + pow(jCenter - j, 2) * 1.0); | ||||
| } | ||||
|  | ||||
| double sumOffset(double* sizes, int init, int offset, int coord) | ||||
| { | ||||
|     double sum = 0; | ||||
|  | ||||
|     for (int i = init - offset; coord > 0; i -= offset, --coord) { | ||||
|         sum += sizes[i]; | ||||
|     } | ||||
|  | ||||
|     return sum; | ||||
| } | ||||
|  | ||||
| void print(Discretization* d, double* grid) | ||||
| { | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|  | ||||
|     for (int i = 0; i < d->comm.size; i++) { | ||||
|         if (i == d->comm.rank) { | ||||
|             sleep(1 * d->comm.rank); | ||||
|             printf("### RANK %d LVL " | ||||
|                    "###################################################### #\n ", | ||||
|                 d->comm.rank); | ||||
|             for (int j = 0; j < d->comm.jmaxLocal + 2; j++) { | ||||
|                 printf("%02d: ", j); | ||||
|                 for (int i = 0; i < d->comm.imaxLocal + 2; i++) { | ||||
|                     printf("%2.2f  ", grid[j * (imaxLocal + 2) + i]); | ||||
|                 } | ||||
|                 printf("\n"); | ||||
|             } | ||||
|             fflush(stdout); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void printConfig(Discretization* d) | ||||
| { | ||||
|     if (commIsMaster(&d->comm)) { | ||||
|         printf("Parameters for #%s#\n", d->problem); | ||||
|         printf("BC Left:%d Right:%d Bottom:%d Top:%d\n", | ||||
|             d->bcLeft, | ||||
|             d->bcRight, | ||||
|             d->bcBottom, | ||||
|             d->bcTop); | ||||
|         printf("\tReynolds number: %.2f\n", d->re); | ||||
|         printf("\tGx Gy: %.2f %.2f\n", d->gx, d->gy); | ||||
|         printf("Geometry data:\n"); | ||||
|         printf("\tDomain box size (x, y): %.2f, %.2f\n", | ||||
|             d->grid.xlength, | ||||
|             d->grid.ylength); | ||||
|         printf("\tCells (x, y): %d, %d\n", d->grid.imax, d->grid.jmax); | ||||
|         printf("\tCell size (dx, dy): %f, %f\n", d->grid.dx, d->grid.dy); | ||||
|         printf("Timestep parameters:\n"); | ||||
|         printf("\tDefault stepsize: %.2f, Final time %.2f\n", d->dt, d->te); | ||||
|         printf("\tdt bound: %.6f\n", d->dtBound); | ||||
|         printf("\tTau factor: %.2f\n", d->tau); | ||||
|         printf("Iterative s parameters:\n"); | ||||
|         printf("\tgamma factor: %f\n", d->gamma); | ||||
|     } | ||||
|     commPrintConfig(&d->comm); | ||||
| } | ||||
|  | ||||
| void initDiscretiztion(Discretization* d, Parameter* params) | ||||
| { | ||||
|     d->problem      = params->name; | ||||
|     d->bcLeft       = params->bcLeft; | ||||
|     d->bcRight      = params->bcRight; | ||||
|     d->bcBottom     = params->bcBottom; | ||||
|     d->bcTop        = params->bcTop; | ||||
|     d->grid.imax    = params->imax; | ||||
|     d->grid.jmax    = params->jmax; | ||||
|     d->grid.xlength = params->xlength; | ||||
|     d->grid.ylength = params->ylength; | ||||
|     d->grid.dx      = params->xlength / params->imax; | ||||
|     d->grid.dy      = params->ylength / params->jmax; | ||||
|     d->re           = params->re; | ||||
|     d->gx           = params->gx; | ||||
|     d->gy           = params->gy; | ||||
|     d->dt           = params->dt; | ||||
|     d->te           = params->te; | ||||
|     d->tau          = params->tau; | ||||
|     d->gamma        = params->gamma; | ||||
|  | ||||
|     /* allocate arrays */ | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|     size_t size   = (imaxLocal + 2) * (jmaxLocal + 2); | ||||
|  | ||||
|     d->u      = allocate(64, size * sizeof(double)); | ||||
|     d->v      = allocate(64, size * sizeof(double)); | ||||
|     d->p      = allocate(64, size * sizeof(double)); | ||||
|     d->rhs    = allocate(64, size * sizeof(double)); | ||||
|     d->f      = allocate(64, size * sizeof(double)); | ||||
|     d->g      = allocate(64, size * sizeof(double)); | ||||
|     d->grid.s = allocate(64, size * sizeof(double)); | ||||
|  | ||||
|     for (int i = 0; i < size; i++) { | ||||
|         d->u[i]      = params->u_init; | ||||
|         d->v[i]      = params->v_init; | ||||
|         d->p[i]      = params->p_init; | ||||
|         d->rhs[i]    = 0.0; | ||||
|         d->f[i]      = 0.0; | ||||
|         d->g[i]      = 0.0; | ||||
|         d->grid.s[i] = FLUID; | ||||
|     } | ||||
|  | ||||
|     double dx = d->grid.dx; | ||||
|     double dy = d->grid.dy; | ||||
|  | ||||
|     double invSqrSum = 1.0 / (dx * dx) + 1.0 / (dy * dy); | ||||
|     d->dtBound       = 0.5 * d->re * 1.0 / invSqrSum; | ||||
|  | ||||
|     d->xLocal = d->comm.imaxLocal * d->grid.dx; | ||||
|     d->yLocal = d->comm.jmaxLocal * d->grid.dy; | ||||
|  | ||||
|     double xLocal[d->comm.size]; | ||||
|     double yLocal[d->comm.size]; | ||||
|  | ||||
| #ifdef _MPI | ||||
|     MPI_Allgather(&d->xLocal, 1, MPI_DOUBLE, xLocal, 1, MPI_DOUBLE, d->comm.comm); | ||||
|     MPI_Allgather(&d->yLocal, 1, MPI_DOUBLE, yLocal, 1, MPI_DOUBLE, d->comm.comm); | ||||
| #endif | ||||
|  | ||||
|     d->xOffset    = sumOffset(xLocal, | ||||
|         d->comm.rank, | ||||
|         d->comm.dims[JDIM], | ||||
|         d->comm.coords[IDIM]); | ||||
|     d->yOffset    = sumOffset(yLocal, d->comm.rank, 1, d->comm.coords[JDIM]); | ||||
|     d->xOffsetEnd = d->xOffset + d->xLocal; | ||||
|     d->yOffsetEnd = d->yOffset + d->yLocal; | ||||
|  | ||||
|     printf("Rank : %d, xOffset : %.2f, yOffset : %.2f, xOffsetEnd : %.2f, yOffsetEnd : " | ||||
|            "%.2f\n", | ||||
|         d->comm.rank, | ||||
|         d->xOffset, | ||||
|         d->yOffset, | ||||
|         d->xOffsetEnd, | ||||
|         d->yOffsetEnd); | ||||
|  | ||||
|     double* s   = d->grid.s; | ||||
|     int iOffset = 0, jOffset = 0; | ||||
|  | ||||
|     double xCenter = 0, yCenter = 0, radius = 0; | ||||
|     double x1 = 0, x2 = 0, y1 = 0, y2 = 0; | ||||
|  | ||||
|     switch (params->shape) { | ||||
|     case NOSHAPE: | ||||
|         break; | ||||
|     case RECT: | ||||
|         x1 = params->xCenter - params->xRectLength / 2; | ||||
|         x2 = params->xCenter + params->xRectLength / 2; | ||||
|         y1 = params->yCenter - params->yRectLength / 2; | ||||
|         y2 = params->yCenter + params->yRectLength / 2; | ||||
|  | ||||
|         iOffset = d->xOffset / dx; | ||||
|         jOffset = d->yOffset / dy; | ||||
|  | ||||
|         for (int j = 1; j < jmaxLocal + 1; ++j) { | ||||
|             for (int i = 1; i < imaxLocal + 1; ++i) { | ||||
|                 if ((x1 <= ((i + iOffset) * dx)) && (((i + iOffset) * dx) <= x2) && | ||||
|                     (y1 <= ((j + jOffset) * dy)) && (((j + jOffset) * dy) <= y2)) { | ||||
|                     S(i, j) = OBSTACLE; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         break; | ||||
|     case CIRCLE: | ||||
|         xCenter = params->xCenter; | ||||
|         yCenter = params->yCenter; | ||||
|         radius  = params->circleRadius; | ||||
|  | ||||
|         iOffset = d->xOffset / dx; | ||||
|         jOffset = d->yOffset / dy; | ||||
|  | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 if (distance(((i + iOffset) * dx), | ||||
|                         ((j + jOffset) * dy), | ||||
|                         xCenter, | ||||
|                         yCenter) <= radius) { | ||||
|                     S(i, j) = OBSTACLE; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|  | ||||
| #ifdef _MPI | ||||
|     commExchange(&d->comm, s); | ||||
| #endif | ||||
|  | ||||
|     for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             if (S(i, j - 1) == FLUID && S(i, j + 1) == OBSTACLE && S(i, j) == OBSTACLE) | ||||
|                 S(i, j) = BOTTOM; // BOTTOM | ||||
|             if (S(i - 1, j) == FLUID && S(i + 1, j) == OBSTACLE && S(i, j) == OBSTACLE) | ||||
|                 S(i, j) = LEFT; // LEFT | ||||
|             if (S(i + 1, j) == FLUID && S(i - 1, j) == OBSTACLE && S(i, j) == OBSTACLE) | ||||
|                 S(i, j) = RIGHT; // RIGHT | ||||
|             if (S(i, j + 1) == FLUID && S(i, j - 1) == OBSTACLE && S(i, j) == OBSTACLE) | ||||
|                 S(i, j) = TOP; // TOP | ||||
|             if (S(i - 1, j - 1) == FLUID && S(i, j - 1) == FLUID && | ||||
|                 S(i - 1, j) == FLUID && S(i + 1, j + 1) == OBSTACLE && | ||||
|                 (S(i, j) == OBSTACLE || S(i, j) == LEFT || S(i, j) == BOTTOM)) | ||||
|                 S(i, j) = BOTTOMLEFT; // BOTTOMLEFT | ||||
|             if (S(i + 1, j - 1) == FLUID && S(i, j - 1) == FLUID && | ||||
|                 S(i + 1, j) == FLUID && S(i - 1, j + 1) == OBSTACLE && | ||||
|                 (S(i, j) == OBSTACLE || S(i, j) == RIGHT || S(i, j) == BOTTOM)) | ||||
|                 S(i, j) = BOTTOMRIGHT; // BOTTOMRIGHT | ||||
|             if (S(i - 1, j + 1) == FLUID && S(i - 1, j) == FLUID && | ||||
|                 S(i, j + 1) == FLUID && S(i + 1, j - 1) == OBSTACLE && | ||||
|                 (S(i, j) == OBSTACLE || S(i, j) == LEFT || S(i, j) == TOP)) | ||||
|                 S(i, j) = TOPLEFT; // TOPLEFT | ||||
|             if (S(i + 1, j + 1) == FLUID && S(i + 1, j) == FLUID && | ||||
|                 S(i, j + 1) == FLUID && S(i - 1, j - 1) == OBSTACLE && | ||||
|                 (S(i, j) == OBSTACLE || S(i, j) == RIGHT || S(i, j) == TOP)) | ||||
|                 S(i, j) = TOPRIGHT; // TOPRIGHT | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #ifdef VERBOSE | ||||
|     printConfig(d); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void computeRHS(Discretization* d) | ||||
| { | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|     double idx    = 1.0 / d->grid.dx; | ||||
|     double idy    = 1.0 / d->grid.dy; | ||||
|     double idt    = 1.0 / d->dt; | ||||
|     double* rhs   = d->rhs; | ||||
|     double* f     = d->f; | ||||
|     double* g     = d->g; | ||||
|  | ||||
|     commShift(&d->comm, f, g); | ||||
|  | ||||
|     for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             RHS(i, j) = ((F(i, j) - F(i - 1, j)) * idx + (G(i, j) - G(i, j - 1)) * idy) * | ||||
|                         idt; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static double maxElement(Discretization* d, double* m) | ||||
| { | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|     int size      = (imaxLocal + 2) * (jmaxLocal + 2); | ||||
|     double maxval = DBL_MIN; | ||||
|  | ||||
|     for (int i = 0; i < size; i++) { | ||||
|         maxval = MAX(maxval, fabs(m[i])); | ||||
|     } | ||||
|  | ||||
|     commReduction(&maxval, MAX); | ||||
|     return maxval; | ||||
| } | ||||
|  | ||||
| void computeTimestep(Discretization* d) | ||||
| { | ||||
|     double dt   = d->dtBound; | ||||
|     double dx   = d->grid.dx; | ||||
|     double dy   = d->grid.dy; | ||||
|     double umax = maxElement(d, d->u); | ||||
|     double vmax = maxElement(d, d->v); | ||||
|  | ||||
|     if (umax > 0) { | ||||
|         dt = (dt > dx / umax) ? dx / umax : dt; | ||||
|     } | ||||
|     if (vmax > 0) { | ||||
|         dt = (dt > dy / vmax) ? dy / vmax : dt; | ||||
|     } | ||||
|  | ||||
|     d->dt = dt * d->tau; | ||||
| } | ||||
|  | ||||
| void setBoundaryConditions(Discretization* d) | ||||
| { | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|     double* u     = d->u; | ||||
|     double* v     = d->v; | ||||
|  | ||||
|     if (commIsBoundary(&d->comm, T)) { | ||||
|         switch (d->bcTop) { | ||||
|         case NOSLIP: | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 V(i, jmaxLocal)     = 0.0; | ||||
|                 U(i, jmaxLocal + 1) = -U(i, jmaxLocal); | ||||
|             } | ||||
|             break; | ||||
|         case SLIP: | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 V(i, jmaxLocal)     = 0.0; | ||||
|                 U(i, jmaxLocal + 1) = U(i, jmaxLocal); | ||||
|             } | ||||
|             break; | ||||
|         case OUTFLOW: | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 U(i, jmaxLocal + 1) = U(i, jmaxLocal); | ||||
|                 V(i, jmaxLocal)     = V(i, jmaxLocal - 1); | ||||
|             } | ||||
|             break; | ||||
|         case PERIODIC: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(&d->comm, B)) { | ||||
|         switch (d->bcBottom) { | ||||
|         case NOSLIP: | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 V(i, 0) = 0.0; | ||||
|                 U(i, 0) = -U(i, 1); | ||||
|             } | ||||
|             break; | ||||
|         case SLIP: | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 V(i, 0) = 0.0; | ||||
|                 U(i, 0) = U(i, 1); | ||||
|             } | ||||
|             break; | ||||
|         case OUTFLOW: | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 U(i, 0) = U(i, 1); | ||||
|                 V(i, 0) = V(i, 1); | ||||
|             } | ||||
|             break; | ||||
|         case PERIODIC: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(&d->comm, R)) { | ||||
|         switch (d->bcRight) { | ||||
|         case NOSLIP: | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 U(imaxLocal, j)     = 0.0; | ||||
|                 V(imaxLocal + 1, j) = -V(imaxLocal, j); | ||||
|             } | ||||
|             break; | ||||
|         case SLIP: | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 U(imaxLocal, j)     = 0.0; | ||||
|                 V(imaxLocal + 1, j) = V(imaxLocal, j); | ||||
|             } | ||||
|             break; | ||||
|         case OUTFLOW: | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 U(imaxLocal, j)     = U(imaxLocal - 1, j); | ||||
|                 V(imaxLocal + 1, j) = V(imaxLocal, j); | ||||
|             } | ||||
|             break; | ||||
|         case PERIODIC: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(&d->comm, L)) { | ||||
|         switch (d->bcLeft) { | ||||
|         case NOSLIP: | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 U(0, j) = 0.0; | ||||
|                 V(0, j) = -V(1, j); | ||||
|             } | ||||
|             break; | ||||
|         case SLIP: | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 U(0, j) = 0.0; | ||||
|                 V(0, j) = V(1, j); | ||||
|             } | ||||
|             break; | ||||
|         case OUTFLOW: | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 U(0, j) = U(1, j); | ||||
|                 V(0, j) = V(1, j); | ||||
|             } | ||||
|             break; | ||||
|         case PERIODIC: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void setSpecialBoundaryCondition(Discretization* d) | ||||
| { | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|     double* u     = d->u; | ||||
|     double* s     = d->grid.s; | ||||
|  | ||||
|     if (strcmp(d->problem, "dcavity") == 0) { | ||||
|         if (commIsBoundary(&d->comm, T)) { | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 U(i, jmaxLocal + 1) = 2.0 - U(i, jmaxLocal); | ||||
|             } | ||||
|         } | ||||
|     } else if (strcmp(d->problem, "canal") == 0) { | ||||
|         if (commIsBoundary(&d->comm, L)) { | ||||
|  | ||||
|             double ylength = d->grid.ylength; | ||||
|             double dy      = d->grid.dy; | ||||
|             int rest       = d->grid.jmax % d->comm.dims[JDIM]; | ||||
|             int yc         = d->comm.rank * (d->grid.jmax / d->comm.dims[JDIM]) + | ||||
|                      MIN(rest, d->comm.rank); | ||||
|             double ys = dy * (yc + 0.5); | ||||
|             double y; | ||||
|  | ||||
|             // printf("RANK %d yc: %d ys: %f\n",d->comm.rank, yc, ys); | ||||
|  | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 y       = ys + dy * (j - 0.5); | ||||
|                 U(0, j) = y * (ylength - y) * 4.0 / (ylength * ylength); | ||||
|             } | ||||
|         } | ||||
|     } else if (strcmp(d->problem, "backstep") == 0) { | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             if (S(0, j) == FLUID) U(0, j) = 1.0; | ||||
|         } | ||||
|     } else if (strcmp(d->problem, "karman") == 0) { | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             U(0, j) = 1.0; | ||||
|         } | ||||
|     } | ||||
|     /* print(solver, solver->u); */ | ||||
| } | ||||
|  | ||||
| void setObjectBoundaryCondition(Discretization* d) | ||||
| { | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|     double* u     = d->u; | ||||
|     double* v     = d->v; | ||||
|     double* s     = d->grid.s; | ||||
|  | ||||
|     for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             switch ((int)S(i, j)) { | ||||
|             case TOP: | ||||
|                 U(i, j)     = -U(i, j + 1); | ||||
|                 U(i - 1, j) = -U(i - 1, j + 1); | ||||
|                 V(i, j)     = 0.0; | ||||
|                 break; | ||||
|             case BOTTOM: | ||||
|                 U(i, j)     = -U(i, j - 1); | ||||
|                 U(i - 1, j) = -U(i - 1, j - 1); | ||||
|                 V(i, j)     = 0.0; | ||||
|                 break; | ||||
|             case LEFT: | ||||
|                 U(i - 1, j) = 0.0; | ||||
|                 V(i, j)     = -V(i - 1, j); | ||||
|                 V(i, j - 1) = -V(i - 1, j - 1); | ||||
|                 break; | ||||
|             case RIGHT: | ||||
|                 U(i, j)     = 0.0; | ||||
|                 V(i, j)     = -V(i + 1, j); | ||||
|                 V(i, j - 1) = -V(i + 1, j - 1); | ||||
|                 break; | ||||
|             case TOPLEFT: | ||||
|                 U(i, j)     = -U(i, j + 1); | ||||
|                 U(i - 1, j) = 0.0; | ||||
|                 V(i, j)     = 0.0; | ||||
|                 V(i, j - 1) = -V(i - 1, j - 1); | ||||
|                 break; | ||||
|             case TOPRIGHT: | ||||
|                 U(i, j)     = 0.0; | ||||
|                 U(i - 1, j) = -U(i - 1, j + 1); | ||||
|                 V(i, j)     = 0.0; | ||||
|                 V(i, j - 1) = -V(i + 1, j - 1); | ||||
|                 break; | ||||
|             case BOTTOMLEFT: | ||||
|                 U(i, j)     = -U(i, j - 1); | ||||
|                 U(i - 1, j) = 0.0; | ||||
|                 V(i, j)     = -V(i - 1, j); | ||||
|                 V(i, j - 1) = 0.0; | ||||
|                 break; | ||||
|             case BOTTOMRIGHT: | ||||
|                 U(i, j)     = 0.0; | ||||
|                 U(i - 1, j) = -U(i - 1, j - 1); | ||||
|                 V(i, j)     = -V(i, j + 1); | ||||
|                 V(i, j - 1) = 0.0; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void computeFG(Discretization* d) | ||||
| { | ||||
|     double* u = d->u; | ||||
|     double* v = d->v; | ||||
|     double* f = d->f; | ||||
|     double* g = d->g; | ||||
|     double* s = d->grid.s; | ||||
|  | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|  | ||||
|     double gx        = d->gx; | ||||
|     double gy        = d->gy; | ||||
|     double gamma     = d->gamma; | ||||
|     double dt        = d->dt; | ||||
|     double inverseRe = 1.0 / d->re; | ||||
|     double inverseDx = 1.0 / d->grid.dx; | ||||
|     double inverseDy = 1.0 / d->grid.dy; | ||||
|     double du2dx, dv2dy, duvdx, duvdy; | ||||
|     double du2dx2, du2dy2, dv2dx2, dv2dy2; | ||||
|  | ||||
|     commExchange(&d->comm, u); | ||||
|     commExchange(&d->comm, v); | ||||
|  | ||||
|     for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             if (S(i, j) == FLUID) { | ||||
|                 du2dx = inverseDx * 0.25 * | ||||
|                             ((U(i, j) + U(i + 1, j)) * (U(i, j) + U(i + 1, j)) - | ||||
|                                 (U(i, j) + U(i - 1, j)) * (U(i, j) + U(i - 1, j))) + | ||||
|                         gamma * inverseDx * 0.25 * | ||||
|                             (fabs(U(i, j) + U(i + 1, j)) * (U(i, j) - U(i + 1, j)) + | ||||
|                                 fabs(U(i, j) + U(i - 1, j)) * (U(i, j) - U(i - 1, j))); | ||||
|  | ||||
|                 duvdy = inverseDy * 0.25 * | ||||
|                             ((V(i, j) + V(i + 1, j)) * (U(i, j) + U(i, j + 1)) - | ||||
|                                 (V(i, j - 1) + V(i + 1, j - 1)) * | ||||
|                                     (U(i, j) + U(i, j - 1))) + | ||||
|                         gamma * inverseDy * 0.25 * | ||||
|                             (fabs(V(i, j) + V(i + 1, j)) * (U(i, j) - U(i, j + 1)) + | ||||
|                                 fabs(V(i, j - 1) + V(i + 1, j - 1)) * | ||||
|                                     (U(i, j) - U(i, j - 1))); | ||||
|  | ||||
|                 du2dx2 = inverseDx * inverseDx * | ||||
|                          (U(i + 1, j) - 2.0 * U(i, j) + U(i - 1, j)); | ||||
|                 du2dy2 = inverseDy * inverseDy * | ||||
|                          (U(i, j + 1) - 2.0 * U(i, j) + U(i, j - 1)); | ||||
|                 F(i, j) = U(i, j) + | ||||
|                           dt * (inverseRe * (du2dx2 + du2dy2) - du2dx - duvdy + gx); | ||||
|  | ||||
|                 duvdx = inverseDx * 0.25 * | ||||
|                             ((U(i, j) + U(i, j + 1)) * (V(i, j) + V(i + 1, j)) - | ||||
|                                 (U(i - 1, j) + U(i - 1, j + 1)) * | ||||
|                                     (V(i, j) + V(i - 1, j))) + | ||||
|                         gamma * inverseDx * 0.25 * | ||||
|                             (fabs(U(i, j) + U(i, j + 1)) * (V(i, j) - V(i + 1, j)) + | ||||
|                                 fabs(U(i - 1, j) + U(i - 1, j + 1)) * | ||||
|                                     (V(i, j) - V(i - 1, j))); | ||||
|  | ||||
|                 dv2dy = inverseDy * 0.25 * | ||||
|                             ((V(i, j) + V(i, j + 1)) * (V(i, j) + V(i, j + 1)) - | ||||
|                                 (V(i, j) + V(i, j - 1)) * (V(i, j) + V(i, j - 1))) + | ||||
|                         gamma * inverseDy * 0.25 * | ||||
|                             (fabs(V(i, j) + V(i, j + 1)) * (V(i, j) - V(i, j + 1)) + | ||||
|                                 fabs(V(i, j) + V(i, j - 1)) * (V(i, j) - V(i, j - 1))); | ||||
|  | ||||
|                 dv2dx2 = inverseDx * inverseDx * | ||||
|                          (V(i + 1, j) - 2.0 * V(i, j) + V(i - 1, j)); | ||||
|                 dv2dy2 = inverseDy * inverseDy * | ||||
|                          (V(i, j + 1) - 2.0 * V(i, j) + V(i, j - 1)); | ||||
|                 G(i, j) = V(i, j) + | ||||
|                           dt * (inverseRe * (dv2dx2 + dv2dy2) - duvdx - dv2dy + gy); | ||||
|             } else { | ||||
|                 switch ((int)S(i, j)) { | ||||
|                 case TOP: | ||||
|                     G(i, j) = V(i, j); | ||||
|                     break; | ||||
|                 case BOTTOM: | ||||
|                     G(i, j - 1) = V(i, j - 1); | ||||
|                     break; | ||||
|                 case LEFT: | ||||
|                     F(i - 1, j) = U(i - 1, j); | ||||
|                     break; | ||||
|                 case RIGHT: | ||||
|                     F(i, j) = U(i, j); | ||||
|                     break; | ||||
|                 case TOPLEFT: | ||||
|                     F(i - 1, j) = U(i - 1, j); | ||||
|                     G(i, j)     = V(i, j); | ||||
|                     break; | ||||
|                 case TOPRIGHT: | ||||
|                     F(i, j) = U(i, j); | ||||
|                     G(i, j) = V(i, j); | ||||
|                     break; | ||||
|                 case BOTTOMLEFT: | ||||
|                     F(i - 1, j) = U(i - 1, j); | ||||
|                     G(i, j - 1) = V(i, j - 1); | ||||
|                     break; | ||||
|                 case BOTTOMRIGHT: | ||||
|                     F(i, j)     = U(i, j); | ||||
|                     G(i, j - 1) = V(i, j - 1); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* ----------------------------- boundary of F --------------------------- */ | ||||
|     if (commIsBoundary(&d->comm, L)) { | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             F(0, j) = U(0, j); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(&d->comm, R)) { | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             F(imaxLocal, j) = U(imaxLocal, j); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* ----------------------------- boundary of G --------------------------- */ | ||||
|     if (commIsBoundary(&d->comm, B)) { | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             G(i, 0) = V(i, 0); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(&d->comm, T)) { | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             G(i, jmaxLocal) = V(i, jmaxLocal); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void adaptUV(Discretization* d) | ||||
| { | ||||
|     int imaxLocal = d->comm.imaxLocal; | ||||
|     int jmaxLocal = d->comm.jmaxLocal; | ||||
|  | ||||
|     double* p = d->p; | ||||
|     double* u = d->u; | ||||
|     double* v = d->v; | ||||
|     double* f = d->f; | ||||
|     double* g = d->g; | ||||
|  | ||||
|     double factorX = d->dt / d->grid.dx; | ||||
|     double factorY = d->dt / d->grid.dy; | ||||
|  | ||||
|     for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             U(i, j) = F(i, j) - (P(i + 1, j) - P(i, j)) * factorX; | ||||
|             V(i, j) = G(i, j) - (P(i, j + 1) - P(i, j)) * factorY; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void writeResult(Discretization* d, double* u, double* v, double* p) | ||||
| { | ||||
|     int imax  = d->grid.imax; | ||||
|     int jmax  = d->grid.jmax; | ||||
|     double dx = d->grid.dx; | ||||
|     double dy = d->grid.dy; | ||||
|     double x = 0.0, y = 0.0; | ||||
|  | ||||
|     FILE* fp; | ||||
|     fp = fopen("pressure.dat", "w"); | ||||
|  | ||||
|     if (fp == NULL) { | ||||
|         printf("Error!\n"); | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
|  | ||||
|     for (int j = 1; j <= jmax; j++) { | ||||
|         y = (double)(j - 0.5) * dy; | ||||
|         for (int i = 1; i <= imax; i++) { | ||||
|             x = (double)(i - 0.5) * dx; | ||||
|             fprintf(fp, "%.2f %.2f %f\n", x, y, p[j * (imax + 2) + i]); | ||||
|         } | ||||
|         fprintf(fp, "\n"); | ||||
|     } | ||||
|  | ||||
|     fclose(fp); | ||||
|  | ||||
|     fp = fopen("velocity.dat", "w"); | ||||
|  | ||||
|     if (fp == NULL) { | ||||
|         printf("Error!\n"); | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
|  | ||||
|     for (int j = 1; j <= jmax; j++) { | ||||
|         y = dy * (j - 0.5); | ||||
|         for (int i = 1; i <= imax; i++) { | ||||
|             x           = dx * (i - 0.5); | ||||
|             double velU = (u[j * (imax + 2) + i] + u[j * (imax + 2) + (i - 1)]) / 2.0; | ||||
|             double velV = (v[j * (imax + 2) + i] + v[(j - 1) * (imax + 2) + i]) / 2.0; | ||||
|             double len  = sqrt((velU * velU) + (velV * velV)); | ||||
|             fprintf(fp, "%.2f %.2f %f %f %f\n", x, y, velU, velV, len); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fclose(fp); | ||||
| } | ||||
							
								
								
									
										66
									
								
								EnhancedSolver/2D-mpi/src/discretization.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								EnhancedSolver/2D-mpi/src/discretization.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __DISCRETIZATION_H_ | ||||
| #define __DISCRETIZATION_H_ | ||||
| #include "comm.h" | ||||
| #include "grid.h" | ||||
| #include "parameter.h" | ||||
| #include<unistd.h> | ||||
|  | ||||
| enum BC { NOSLIP = 1, SLIP, OUTFLOW, PERIODIC }; | ||||
|  | ||||
| enum OBJECTBOUNDARY { | ||||
|     FLUID = 0, | ||||
|     TOP, | ||||
|     BOTTOM, | ||||
|     LEFT, | ||||
|     RIGHT, | ||||
|     TOPLEFT, | ||||
|     BOTTOMLEFT, | ||||
|     TOPRIGHT, | ||||
|     BOTTOMRIGHT, | ||||
|     OBSTACLE | ||||
| }; | ||||
|  | ||||
| enum SHAPE { NOSHAPE = 0, RECT, CIRCLE }; | ||||
|  | ||||
| typedef struct { | ||||
|     /* geometry and grid information */ | ||||
|     Grid grid; | ||||
|     /* arrays */ | ||||
|     double *p, *rhs; | ||||
|     double *f, *g; | ||||
|     double *u, *v; | ||||
|     /* parameters */ | ||||
|     double re, tau, gamma; | ||||
|     double gx, gy; | ||||
|     /* time stepping */ | ||||
|     double dt, te; | ||||
|     double dtBound; | ||||
|     char* problem; | ||||
|  | ||||
|     double xLocal, yLocal, xOffset, yOffset, xOffsetEnd, yOffsetEnd; | ||||
|  | ||||
|  | ||||
|     int bcLeft, bcRight, bcBottom, bcTop; | ||||
|     /* communication */ | ||||
|     Comm comm; | ||||
| } Discretization; | ||||
|  | ||||
| extern void initDiscretiztion(Discretization*, Parameter*); | ||||
| extern void computeRHS(Discretization*); | ||||
| extern void normalizePressure(Discretization*); | ||||
| extern void computeTimestep(Discretization*); | ||||
| extern void setBoundaryConditions(Discretization*); | ||||
| extern void setSpecialBoundaryCondition(Discretization*); | ||||
| extern void setObjectBoundaryCondition(Discretization*); | ||||
| extern void computeFG(Discretization*); | ||||
| extern void adaptUV(Discretization*); | ||||
| extern void writeResult(Discretization* s, double* u, double* v, double* p); | ||||
| extern double sumOffset(double* , int , int , int ); | ||||
| extern void print(Discretization* , double* ); | ||||
| #endif | ||||
							
								
								
									
										17
									
								
								EnhancedSolver/2D-mpi/src/grid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								EnhancedSolver/2D-mpi/src/grid.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| /* | ||||
|  * Copyright (C) NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __GRID_H_ | ||||
| #define __GRID_H_ | ||||
|  | ||||
| typedef struct { | ||||
|     double dx, dy; | ||||
|     int imax, jmax; | ||||
|     double xlength, ylength; | ||||
|     double* s; | ||||
| } Grid; | ||||
|  | ||||
| #endif // __GRID_H_ | ||||
							
								
								
									
										54
									
								
								EnhancedSolver/2D-mpi/src/likwid-marker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								EnhancedSolver/2D-mpi/src/likwid-marker.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| /* | ||||
|  * ======================================================================================= | ||||
|  * | ||||
|  *      Author:   Jan Eitzinger (je), jan.eitzinger@fau.de | ||||
|  *      Copyright (c) 2020 RRZE, University Erlangen-Nuremberg | ||||
|  * | ||||
|  *      Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  *      of this software and associated documentation files (the "Software"), to deal | ||||
|  *      in the Software without restriction, including without limitation the rights | ||||
|  *      to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  *      copies of the Software, and to permit persons to whom the Software is | ||||
|  *      furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  *      The above copyright notice and this permission notice shall be included in all | ||||
|  *      copies or substantial portions of the Software. | ||||
|  * | ||||
|  *      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  *      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  *      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  *      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  *      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  *      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  *      SOFTWARE. | ||||
|  * | ||||
|  * ======================================================================================= | ||||
|  */ | ||||
| #ifndef LIKWID_MARKERS_H | ||||
| #define LIKWID_MARKERS_H | ||||
|  | ||||
| #ifdef LIKWID_PERFMON | ||||
| #include <likwid.h> | ||||
| #define LIKWID_MARKER_INIT                likwid_markerInit() | ||||
| #define LIKWID_MARKER_THREADINIT          likwid_markerThreadInit() | ||||
| #define LIKWID_MARKER_SWITCH              likwid_markerNextGroup() | ||||
| #define LIKWID_MARKER_REGISTER(regionTag) likwid_markerRegisterRegion(regionTag) | ||||
| #define LIKWID_MARKER_START(regionTag)    likwid_markerStartRegion(regionTag) | ||||
| #define LIKWID_MARKER_STOP(regionTag)     likwid_markerStopRegion(regionTag) | ||||
| #define LIKWID_MARKER_CLOSE               likwid_markerClose() | ||||
| #define LIKWID_MARKER_RESET(regionTag)    likwid_markerResetRegion(regionTag) | ||||
| #define LIKWID_MARKER_GET(regionTag, nevents, events, time, count)                       \ | ||||
|     likwid_markerGetRegion(regionTag, nevents, events, time, count) | ||||
| #else /* LIKWID_PERFMON */ | ||||
| #define LIKWID_MARKER_INIT | ||||
| #define LIKWID_MARKER_THREADINIT | ||||
| #define LIKWID_MARKER_SWITCH | ||||
| #define LIKWID_MARKER_REGISTER(regionTag) | ||||
| #define LIKWID_MARKER_START(regionTag) | ||||
| #define LIKWID_MARKER_STOP(regionTag) | ||||
| #define LIKWID_MARKER_CLOSE | ||||
| #define LIKWID_MARKER_GET(regionTag, nevents, events, time, count) | ||||
| #define LIKWID_MARKER_RESET(regionTag) | ||||
| #endif /* LIKWID_PERFMON */ | ||||
|  | ||||
| #endif /*LIKWID_MARKERS_H*/ | ||||
							
								
								
									
										120
									
								
								EnhancedSolver/2D-mpi/src/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								EnhancedSolver/2D-mpi/src/main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| /* | ||||
|  * Copyright (C) NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "allocate.h" | ||||
| #include "comm.h" | ||||
| #include "discretization.h" | ||||
| #include "grid.h" | ||||
| #include "parameter.h" | ||||
| #include "particletracing.h" | ||||
| #include "progress.h" | ||||
| #include "timing.h" | ||||
|  | ||||
| static void writeResults(Discretization* s) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     size_t bytesize = (s->grid.imax + 2) * (s->grid.jmax + 2) * sizeof(double); | ||||
|  | ||||
|     double* ug = allocate(64, bytesize); | ||||
|     double* vg = allocate(64, bytesize); | ||||
|     double* pg = allocate(64, bytesize); | ||||
|  | ||||
|     commCollectResult(&s->comm, ug, vg, pg, s->u, s->v, s->p, s->grid.imax, s->grid.jmax); | ||||
|     if (commIsMaster(&s->comm)) { | ||||
|         writeResult(s, ug, vg, pg); | ||||
|     } | ||||
|  | ||||
|     free(ug); | ||||
|     free(vg); | ||||
|     free(pg); | ||||
| #else | ||||
|     writeResult(s, s->u, s->v, s->p); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     int rank; | ||||
|     double timeStart, timeStop; | ||||
|     Parameter p; | ||||
|     Discretization d; | ||||
|     Solver s; | ||||
|     ParticleTracer particletracer; | ||||
|  | ||||
|     commInit(&d.comm, argc, argv); | ||||
|     initParameter(&p); | ||||
|  | ||||
|     if (argc != 2) { | ||||
|         printf("Usage: %s <configFile>\n", argv[0]); | ||||
|         exit(EXIT_SUCCESS); | ||||
|     } | ||||
|  | ||||
|     readParameter(&p, argv[1]); | ||||
|     commPartition(&d.comm, p.jmax, p.imax); | ||||
|     if (commIsMaster(&d.comm)) { | ||||
|         printParameter(&p); | ||||
|     } | ||||
|  | ||||
|     initDiscretiztion(&d, &p); | ||||
|     initSolver(&s, &d, &p); | ||||
|     initParticleTracer(&particletracer, &d, &p); | ||||
|  | ||||
| #ifdef TEST | ||||
|     commPrintConfig(&d.comm); | ||||
|     commTestInit(&d.comm, d.p, d.f, d.g); | ||||
|     commExchange(&d.comm, d.p); | ||||
|     commShift(&d.comm, d.f, d.g); | ||||
|     commTestWrite(&d.comm, d.p, d.f, d.g); | ||||
|     writeResults(&d); | ||||
|     commFinalize(&d.comm); | ||||
|     exit(EXIT_SUCCESS); | ||||
| #endif | ||||
| #ifndef VERBOSE | ||||
|     initProgress(d.te); | ||||
| #endif | ||||
|  | ||||
|     double tau = d.tau; | ||||
|     double te  = d.te; | ||||
|     double t   = 0.0; | ||||
|  | ||||
|     timeStart = getTimeStamp(); | ||||
|     while (t <= te) { | ||||
|         if (tau > 0.0) computeTimestep(&d); | ||||
|         setBoundaryConditions(&d); | ||||
|         setSpecialBoundaryCondition(&d); | ||||
|         setObjectBoundaryCondition(&d); | ||||
|         computeFG(&d); | ||||
|         computeRHS(&d); | ||||
|         solve(&s, d.p, d.rhs); | ||||
|         adaptUV(&d); | ||||
|         trace(&particletracer, &d, t); | ||||
|         t += d.dt; | ||||
|  | ||||
| #ifdef VERBOSE | ||||
|         if (commIsMaster(s.comm)) { | ||||
|             printf("TIME %f , TIMESTEP %f\n", t, d.dt); | ||||
|         } | ||||
| #else | ||||
|         printProgress(t); | ||||
| #endif | ||||
|     } | ||||
|     timeStop = getTimeStamp(); | ||||
| #ifndef VERBOSE | ||||
|     stopProgress(); | ||||
| #endif | ||||
|     if (commIsMaster(s.comm)) { | ||||
|         printf("Solution took %.2fs\n", timeStop - timeStart); | ||||
|     } | ||||
|  | ||||
|     freeParticles(&particletracer); | ||||
|     writeResults(&d); | ||||
|     commFinalize(s.comm); | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
							
								
								
									
										143
									
								
								EnhancedSolver/2D-mpi/src/parameter.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								EnhancedSolver/2D-mpi/src/parameter.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "parameter.h" | ||||
| #include "util.h" | ||||
| #define MAXLINE 4096 | ||||
|  | ||||
| void initParameter(Parameter* param) | ||||
| { | ||||
|     param->xlength    = 1.0; | ||||
|     param->ylength    = 1.0; | ||||
|     param->imax       = 100; | ||||
|     param->jmax       = 100; | ||||
|     param->itermax    = 1000; | ||||
|     param->eps        = 0.0001; | ||||
|     param->omg        = 1.8; | ||||
|     param->levels     = 5; | ||||
|     param->presmooth  = 5; | ||||
|     param->postsmooth = 5; | ||||
| } | ||||
|  | ||||
| void readParameter(Parameter* param, const char* filename) | ||||
| { | ||||
|     FILE* fp = fopen(filename, "r"); | ||||
|     char line[MAXLINE]; | ||||
|     int i; | ||||
|  | ||||
|     if (!fp) { | ||||
|         fprintf(stderr, "Could not open parameter file: %s\n", filename); | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
|  | ||||
|     while (!feof(fp)) { | ||||
|         line[0] = '\0'; | ||||
|         fgets(line, MAXLINE, fp); | ||||
|         for (i = 0; line[i] != '\0' && line[i] != '#'; i++) | ||||
|             ; | ||||
|         line[i] = '\0'; | ||||
|  | ||||
|         char* tok = strtok(line, " "); | ||||
|         char* val = strtok(NULL, " "); | ||||
|  | ||||
| #define PARSE_PARAM(p, f)                                                                \ | ||||
|     if (strncmp(tok, #p, sizeof(#p) / sizeof(#p[0]) - 1) == 0) {                         \ | ||||
|         param->p = f(val);                                                               \ | ||||
|     } | ||||
| #define PARSE_STRING(p) PARSE_PARAM(p, strdup) | ||||
| #define PARSE_INT(p)    PARSE_PARAM(p, atoi) | ||||
| #define PARSE_REAL(p)   PARSE_PARAM(p, atof) | ||||
|  | ||||
|         if (tok != NULL && val != NULL) { | ||||
|             PARSE_REAL(xlength); | ||||
|             PARSE_REAL(ylength); | ||||
|             PARSE_INT(imax); | ||||
|             PARSE_INT(jmax); | ||||
|             PARSE_INT(itermax); | ||||
|             PARSE_REAL(eps); | ||||
|             PARSE_REAL(omg); | ||||
|             PARSE_REAL(re); | ||||
|             PARSE_REAL(tau); | ||||
|             PARSE_REAL(gamma); | ||||
|             PARSE_REAL(dt); | ||||
|             PARSE_REAL(te); | ||||
|             PARSE_REAL(gx); | ||||
|             PARSE_REAL(gy); | ||||
|             PARSE_STRING(name); | ||||
|             PARSE_INT(bcLeft); | ||||
|             PARSE_INT(bcRight); | ||||
|             PARSE_INT(bcBottom); | ||||
|             PARSE_INT(bcTop); | ||||
|             PARSE_INT(levels); | ||||
|             PARSE_INT(presmooth); | ||||
|             PARSE_INT(postsmooth); | ||||
|             PARSE_REAL(u_init); | ||||
|             PARSE_REAL(v_init); | ||||
|             PARSE_REAL(p_init); | ||||
|  | ||||
|             /* Added new particle tracing parameters */ | ||||
|             PARSE_INT(numberOfParticles); | ||||
|             PARSE_REAL(startTime); | ||||
|             PARSE_REAL(injectTimePeriod); | ||||
|             PARSE_REAL(writeTimePeriod); | ||||
|             PARSE_REAL(x1); | ||||
|             PARSE_REAL(y1); | ||||
|             PARSE_REAL(x2); | ||||
|             PARSE_REAL(y2); | ||||
|  | ||||
|             /* Added obstacle geometry parameters */ | ||||
|             PARSE_INT(shape); | ||||
|             PARSE_REAL(xCenter); | ||||
|             PARSE_REAL(yCenter); | ||||
|             PARSE_REAL(xRectLength); | ||||
|             PARSE_REAL(yRectLength); | ||||
|             PARSE_REAL(circleRadius); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fclose(fp); | ||||
| } | ||||
|  | ||||
| void printParameter(Parameter* param) | ||||
| { | ||||
|     printf("Parameters for %s\n", param->name); | ||||
|     printf("Boundary conditions Left:%d Right:%d Bottom:%d Top:%d\n", | ||||
|         param->bcLeft, | ||||
|         param->bcRight, | ||||
|         param->bcBottom, | ||||
|         param->bcTop); | ||||
|     printf("\tReynolds number: %.2f\n", param->re); | ||||
|     printf("\tInit arrays: U:%.2f V:%.2f P:%.2f\n", | ||||
|         param->u_init, | ||||
|         param->v_init, | ||||
|         param->p_init); | ||||
|     printf("Geometry data:\n"); | ||||
|     printf("\tDomain box size (x, y): %.2f, %.2f\n", param->xlength, param->ylength); | ||||
|     printf("\tCells (x, y): %d, %d\n", param->imax, param->jmax); | ||||
|     printf("Timestep parameters:\n"); | ||||
|     printf("\tDefault stepsize: %.2f, Final time %.2f\n", param->dt, param->te); | ||||
|     printf("\tTau factor: %.2f\n", param->tau); | ||||
|     printf("Iterative solver parameters:\n"); | ||||
|     printf("\tMax iterations: %d\n", param->itermax); | ||||
|     printf("\tepsilon (stopping tolerance) : %f\n", param->eps); | ||||
|     printf("\tgamma (stopping tolerance) : %f\n", param->gamma); | ||||
|     printf("\tomega (SOR relaxation): %f\n", param->omg); | ||||
|     printf("Particle tracer parameters:\n"); | ||||
|     printf("\tNumber of particles: %d\n", param->numberOfParticles); | ||||
|     printf("\tstartTime : %f\n", param->startTime); | ||||
|     printf("\tinjecTimePeriod : %f\n", param->injectTimePeriod); | ||||
|     printf("\twriteTimePeriod: %f\n", param->writeTimePeriod); | ||||
|     printf("\tx1 : %f, x2 : %f, y1 : %f, y2 : %f\n", | ||||
|         param->x1, | ||||
|         param->x2, | ||||
|         param->y1, | ||||
|         param->y2); | ||||
|     printf("\tShape : %d\n", param->shape); | ||||
| } | ||||
							
								
								
									
										38
									
								
								EnhancedSolver/2D-mpi/src/parameter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								EnhancedSolver/2D-mpi/src/parameter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __PARAMETER_H_ | ||||
| #define __PARAMETER_H_ | ||||
|  | ||||
| typedef struct { | ||||
|     double xlength, ylength; | ||||
|     int imax, jmax; | ||||
|     int itermax; | ||||
|     double eps, omg; | ||||
|     double re, tau, gamma; | ||||
|     double te, dt; | ||||
|     double gx, gy; | ||||
|     char* name; | ||||
|     int bcLeft, bcRight, bcBottom, bcTop; | ||||
|     double u_init, v_init, p_init; | ||||
|      | ||||
|     int levels, presmooth, postsmooth; | ||||
|  | ||||
|     int numberOfParticles; | ||||
|     double startTime, injectTimePeriod, writeTimePeriod; | ||||
|  | ||||
|     double x1, y1, x2, y2; | ||||
|  | ||||
|     int shape; | ||||
|     double xCenter, yCenter, xRectLength, yRectLength, circleRadius; | ||||
|  | ||||
|  | ||||
| } Parameter; | ||||
|  | ||||
| void initParameter(Parameter*); | ||||
| void readParameter(Parameter*, const char*); | ||||
| void printParameter(Parameter*); | ||||
| #endif | ||||
							
								
								
									
										612
									
								
								EnhancedSolver/2D-mpi/src/particletracing.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										612
									
								
								EnhancedSolver/2D-mpi/src/particletracing.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,612 @@ | ||||
| /* | ||||
|  * Copyright (C) 2022 NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <float.h> | ||||
| #include <math.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "particletracing.h" | ||||
|  | ||||
| #define U(i, j) u[(j) * (imaxLocal + 2) + (i)] | ||||
| #define V(i, j) v[(j) * (imaxLocal + 2) + (i)] | ||||
| #define S(i, j) s[(j) * (imaxLocal + 2) + (i)] | ||||
|  | ||||
| static int ts = 0; | ||||
|  | ||||
| #define IDIM 0 | ||||
| #define JDIM 1 | ||||
|  | ||||
| #define XOFFSET    0 | ||||
| #define YOFFSET    1 | ||||
| #define XOFFSETEND 2 | ||||
| #define YOFFSETEND 3 | ||||
|  | ||||
| static double sum(int* sizes, int size) | ||||
| { | ||||
|     double sum = 0; | ||||
|  | ||||
|     for (int i = 0; i < size; ++i) { | ||||
|         sum += sizes[i]; | ||||
|     } | ||||
|  | ||||
|     return sum; | ||||
| } | ||||
|  | ||||
| void printUV(ParticleTracer* particletracer, double* u, double* v) | ||||
| { | ||||
|     int imaxLocal = particletracer->imaxLocal; | ||||
|  | ||||
|     for (int i = 0; i < particletracer->size; i++) { | ||||
|         if (i == particletracer->rank) { | ||||
|             printf( | ||||
|                 "\n### RANK %d #######################################################\n", | ||||
|                 particletracer->rank); | ||||
|             printf("\nGrid U : \n"); | ||||
|             for (int j = 0; j < particletracer->jmaxLocal + 2; j++) { | ||||
|                 printf("%02d: ", j); | ||||
|                 for (int i = 0; i < particletracer->imaxLocal + 2; i++) { | ||||
|                     printf("%4.2f  ", u[j * (imaxLocal + 2) + i]); | ||||
|                 } | ||||
|                 printf("\n"); | ||||
|             } | ||||
|             fflush(stdout); | ||||
|             printf("\nGrid V : \n"); | ||||
|             for (int j = 0; j < particletracer->jmaxLocal + 2; j++) { | ||||
|                 printf("%02d: ", j); | ||||
|                 for (int i = 0; i < particletracer->imaxLocal + 2; i++) { | ||||
|                     printf("%4.2f  ", v[j * (imaxLocal + 2) + i]); | ||||
|                 } | ||||
|                 printf("\n"); | ||||
|             } | ||||
|             fflush(stdout); | ||||
|         } | ||||
|  | ||||
| #ifdef _MPI | ||||
|         MPI_Barrier(MPI_COMM_WORLD); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| void initParticleTracer( | ||||
|     ParticleTracer* particletracer, Discretization* d, Parameter* params) | ||||
| { | ||||
|     int dims[NDIMS]    = { 0, 0 }; | ||||
|     int periods[NDIMS] = { 0, 0 }; | ||||
|  | ||||
|     /* initializing local properties from params */ | ||||
|     particletracer->rank = d->comm.rank; | ||||
|     particletracer->size = d->comm.size; | ||||
|  | ||||
|     particletracer->numberOfParticles = params->numberOfParticles; | ||||
|     particletracer->startTime         = params->startTime; | ||||
|     particletracer->injectTimePeriod  = params->injectTimePeriod; | ||||
|     particletracer->writeTimePeriod   = params->writeTimePeriod; | ||||
|  | ||||
|     particletracer->dt = params->dt; | ||||
|     particletracer->dx = params->xlength / params->imax; | ||||
|     particletracer->dy = params->ylength / params->jmax; | ||||
|  | ||||
|     particletracer->xlength = params->xlength; | ||||
|     particletracer->ylength = params->ylength; | ||||
|  | ||||
|     particletracer->x1 = params->x1; | ||||
|     particletracer->y1 = params->y1; | ||||
|     particletracer->x2 = params->x2; | ||||
|     particletracer->y2 = params->y2; | ||||
|  | ||||
|     particletracer->lastInjectTime = params->startTime; | ||||
|     particletracer->lastUpdateTime = params->startTime; | ||||
|     particletracer->lastWriteTime  = params->startTime; | ||||
|  | ||||
|     particletracer->pointer        = 0; | ||||
|     particletracer->totalParticles = 0; | ||||
|  | ||||
|     particletracer->imax = params->imax; | ||||
|     particletracer->jmax = params->jmax; | ||||
|  | ||||
|     particletracer->imaxLocal        = d->comm.imaxLocal; | ||||
|     particletracer->jmaxLocal        = d->comm.jmaxLocal; | ||||
|     particletracer->removedParticles = 0; | ||||
|  | ||||
|     // Estimating the number of particles over the number of timesteps that could be | ||||
|     // required. | ||||
|     particletracer->estimatedNumParticles = (particletracer->imaxLocal * | ||||
|                                              particletracer->jmaxLocal); | ||||
|  | ||||
|     // Allocating memory for the estimated particles over the timesteps. | ||||
|     particletracer->particlePool = malloc( | ||||
|         sizeof(Particle) * particletracer->estimatedNumParticles); | ||||
|  | ||||
|     // Initializing the number of particles to 0 and turning OFF all of the particles. | ||||
|     // Contain information in x and y length metric, not i and j discretization metrics. | ||||
|     for (int i = 0; i < particletracer->estimatedNumParticles; ++i) { | ||||
|         particletracer->particlePool[i].x    = 0.0; | ||||
|         particletracer->particlePool[i].y    = 0.0; | ||||
|         particletracer->particlePool[i].flag = false; | ||||
|     } | ||||
|  | ||||
|     // Creating a linearly spaced particle line. | ||||
|     particletracer->linSpaceLine = malloc( | ||||
|         sizeof(Particle) * particletracer->numberOfParticles); | ||||
|  | ||||
|     // Creating an array for each rank that will hold information about | ||||
|     // offsets from other ranks. Holds each ranks x and y length metrics. | ||||
|     particletracer->offset = (double*)malloc(sizeof(double) * 4 * particletracer->size); | ||||
|  | ||||
|     // Calculating each ranks local x and y length metrics. | ||||
|  | ||||
|     double offset[4][particletracer->size]; | ||||
|  | ||||
|     // Calculating each ranks x and y local lengths. | ||||
|     particletracer->xLocal = d->xLocal; | ||||
|     particletracer->yLocal = d->yLocal; | ||||
|  | ||||
|     double xLocal[particletracer->size]; | ||||
|     double yLocal[particletracer->size]; | ||||
|  | ||||
|     // Calculate own x and y length metric offset based on other ranks offset data. | ||||
|     particletracer->xOffset    = d->xOffset; | ||||
|     particletracer->yOffset    = d->yOffset; | ||||
|     particletracer->xOffsetEnd = d->xOffsetEnd; | ||||
|     particletracer->yOffsetEnd = d->yOffsetEnd; | ||||
|  | ||||
|     printf("Rank : %d, xOffset : %.2f, yOffset : %.2f, xOffsetEnd : %.2f, yOffsetEnd : " | ||||
|            "%.2f\n", | ||||
|         particletracer->rank, | ||||
|         particletracer->xOffset, | ||||
|         particletracer->yOffset, | ||||
|         particletracer->xOffsetEnd, | ||||
|         particletracer->yOffsetEnd); | ||||
|  | ||||
| #ifdef _MPI | ||||
|     // Gather each ranks x and y length metric that marks each ranks own territory. | ||||
|     // Once the boundary leaves local domain, then it needs to know which ranks to send. | ||||
|     // And to know whos boundary it is, we need to know the rank. | ||||
|     MPI_Allgather(&particletracer->xOffset, | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         offset[0], | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         d->comm.comm); | ||||
|     MPI_Allgather(&particletracer->yOffset, | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         offset[1], | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         d->comm.comm); | ||||
|     MPI_Allgather(&particletracer->xOffsetEnd, | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         offset[2], | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         d->comm.comm); | ||||
|     MPI_Allgather(&particletracer->yOffsetEnd, | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         offset[3], | ||||
|         1, | ||||
|         MPI_DOUBLE, | ||||
|         d->comm.comm); | ||||
| #endif | ||||
|  | ||||
|     memcpy(particletracer->offset, offset, sizeof(offset)); | ||||
|  | ||||
|     for (int i = 0; i < particletracer->numberOfParticles; ++i) { | ||||
|         double spacing = (double)i / (double)(particletracer->numberOfParticles - 1); | ||||
|         particletracer->linSpaceLine[i].x = spacing * particletracer->x1 + | ||||
|                                             (1.0 - spacing) * particletracer->x2; | ||||
|         particletracer->linSpaceLine[i].y = spacing * particletracer->y1 + | ||||
|                                             (1.0 - spacing) * particletracer->y2; | ||||
|         particletracer->linSpaceLine[i].flag = true; | ||||
|     } | ||||
|  | ||||
| #ifdef _MPI | ||||
|     // Create the mpi_particle datatype | ||||
|     MPI_Datatype mpi_particle; | ||||
|     int lengths[3] = { 1, 1, 1 }; | ||||
|  | ||||
|     MPI_Aint displacements[3]; | ||||
|     Particle dummy_particle; | ||||
|     MPI_Aint base_address; | ||||
|     MPI_Get_address(&dummy_particle, &base_address); | ||||
|     MPI_Get_address(&dummy_particle.x, &displacements[0]); | ||||
|     MPI_Get_address(&dummy_particle.y, &displacements[1]); | ||||
|     MPI_Get_address(&dummy_particle.flag, &displacements[2]); | ||||
|     displacements[0] = MPI_Aint_diff(displacements[0], base_address); | ||||
|     displacements[1] = MPI_Aint_diff(displacements[1], base_address); | ||||
|     displacements[2] = MPI_Aint_diff(displacements[2], base_address); | ||||
|  | ||||
|     MPI_Datatype types[3] = { MPI_DOUBLE, MPI_DOUBLE, MPI_C_BOOL }; | ||||
|     MPI_Type_create_struct(3, | ||||
|         lengths, | ||||
|         displacements, | ||||
|         types, | ||||
|         &particletracer->mpi_particle); | ||||
|     MPI_Type_commit(&particletracer->mpi_particle); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void printParticles(ParticleTracer* particletracer) | ||||
| { | ||||
|     for (int i = 0; i < particletracer->totalParticles; ++i) { | ||||
|         printf("Rank : %d Particle position X : %.2f, Y : %.2f, flag : %d, total pt : " | ||||
|                "%d, pointer : %d, xOffset : %.2f, yOffset : %.2f, xOffsetEnd : %.2f, " | ||||
|                "yOffsetEnd : %.2f\n", | ||||
|             particletracer->rank, | ||||
|             particletracer->particlePool[i].x, | ||||
|             particletracer->particlePool[i].y, | ||||
|             particletracer->particlePool[i].flag, | ||||
|             particletracer->totalParticles, | ||||
|             particletracer->pointer, | ||||
|             particletracer->xOffset, | ||||
|             particletracer->yOffset, | ||||
|             particletracer->xOffsetEnd, | ||||
|             particletracer->yOffsetEnd); | ||||
|     } | ||||
| } | ||||
| void injectParticles(ParticleTracer* particletracer) | ||||
| { | ||||
|     double x, y; | ||||
|     for (int i = 0; i < particletracer->numberOfParticles; ++i) { | ||||
|         x = particletracer->linSpaceLine[i].x; | ||||
|         y = particletracer->linSpaceLine[i].y; | ||||
|         if (x >= particletracer->xOffset && y >= particletracer->yOffset && | ||||
|             x <= particletracer->xOffsetEnd && y <= particletracer->yOffsetEnd) { | ||||
|  | ||||
|             particletracer->particlePool[particletracer->pointer].x    = x; | ||||
|             particletracer->particlePool[particletracer->pointer].y    = y; | ||||
|             particletracer->particlePool[particletracer->pointer].flag = true; | ||||
|             ++(particletracer->pointer); | ||||
|             ++(particletracer->totalParticles); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void advanceParticles(ParticleTracer* particletracer, | ||||
|     double* restrict u, | ||||
|     double* restrict v, | ||||
|     double* restrict s, | ||||
|     Comm* comm, | ||||
|     double time) | ||||
| { | ||||
|  | ||||
|     int imax      = particletracer->imax; | ||||
|     int jmax      = particletracer->jmax; | ||||
|     int imaxLocal = particletracer->imaxLocal; | ||||
|     int jmaxLocal = particletracer->jmaxLocal; | ||||
|  | ||||
|     double dx = particletracer->dx; | ||||
|     double dy = particletracer->dy; | ||||
|  | ||||
|     double xlength = particletracer->xlength; | ||||
|     double ylength = particletracer->ylength; | ||||
|  | ||||
|     Particle buff[particletracer->size][100]; | ||||
|  | ||||
|     for (int i = 0; i < particletracer->size; ++i) { | ||||
|         for (int j = 0; j < 100; ++j) { | ||||
|             buff[i][j].x    = 0.0; | ||||
|             buff[i][j].y    = 0.0; | ||||
|             buff[i][j].flag = false; | ||||
|         } | ||||
|     } | ||||
|     int particleBufIndex[particletracer->size]; | ||||
|  | ||||
|     memset(particleBufIndex, 0, sizeof(particleBufIndex)); | ||||
|  | ||||
|     for (int i = 0; i < particletracer->totalParticles; ++i) { | ||||
|         if (particletracer->particlePool[i].flag == true) { | ||||
|             double xTemp = particletracer->particlePool[i].x; | ||||
|             double yTemp = particletracer->particlePool[i].y; | ||||
|  | ||||
|             double x = xTemp - particletracer->xOffset; | ||||
|             double y = yTemp - particletracer->yOffset; | ||||
|  | ||||
|             int iCoord = (int)(x / dx) + 1; | ||||
|             int jCoord = (int)((y + 0.5 * dy) / dy) + 1; | ||||
|  | ||||
|             double x1 = (double)(iCoord - 1) * dx; | ||||
|             double y1 = ((double)(jCoord - 1) - 0.5) * dy; | ||||
|             double x2 = (double)iCoord * dx; | ||||
|             double y2 = ((double)jCoord - 0.5) * dy; | ||||
|  | ||||
|             double u_n = (1.0 / (dx * dy)) * | ||||
|                          ((x2 - x) * (y2 - y) * U(iCoord - 1, jCoord - 1) + | ||||
|                              (x - x1) * (y2 - y) * U(iCoord, jCoord - 1) + | ||||
|                              (x2 - x) * (y - y1) * U(iCoord - 1, jCoord) + | ||||
|                              (x - x1) * (y - y1) * U(iCoord, jCoord)); | ||||
|  | ||||
|             double new_x = (x + particletracer->xOffset) + particletracer->dt * u_n; | ||||
|             particletracer->particlePool[i].x = new_x; | ||||
|  | ||||
|             iCoord = (int)((x + 0.5 * dx) / dx) + 1; | ||||
|             jCoord = (int)(y / dy) + 1; | ||||
|  | ||||
|             x1 = ((double)(iCoord - 1) - 0.5) * dx; | ||||
|             y1 = (double)(jCoord - 1) * dy; | ||||
|             x2 = ((double)iCoord - 0.5) * dx; | ||||
|             y2 = (double)jCoord * dy; | ||||
|  | ||||
|             double v_n = (1.0 / (dx * dy)) * | ||||
|                          ((x2 - x) * (y2 - y) * V(iCoord - 1, jCoord - 1) + | ||||
|                              (x - x1) * (y2 - y) * V(iCoord, jCoord - 1) + | ||||
|                              (x2 - x) * (y - y1) * V(iCoord - 1, jCoord) + | ||||
|                              (x - x1) * (y - y1) * V(iCoord, jCoord)); | ||||
|  | ||||
|             double new_y = (y + particletracer->yOffset) + particletracer->dt * v_n; | ||||
|             particletracer->particlePool[i].y = new_y; | ||||
|  | ||||
|             if (((new_x < particletracer->xOffset) || | ||||
|                     (new_x >= particletracer->xOffsetEnd) || | ||||
|                     (new_y < particletracer->yOffset) || | ||||
|                     (new_y >= particletracer->yOffsetEnd))) { | ||||
|                 // New logic to transfer particles to neighbouring ranks or discard the | ||||
|                 // particle. | ||||
|  | ||||
|                 for (int i = 0; i < particletracer->size; ++i) { | ||||
|                     if ((new_x >= | ||||
|                             particletracer->offset[i + particletracer->size * XOFFSET]) && | ||||
|                         (new_x <= particletracer | ||||
|                                       ->offset[i + particletracer->size * XOFFSETEND]) && | ||||
|                         (new_y >= | ||||
|                             particletracer->offset[i + particletracer->size * YOFFSET]) && | ||||
|                         (new_y <= particletracer | ||||
|                                       ->offset[i + particletracer->size * YOFFSETEND]) && | ||||
|                         i != particletracer->rank) { | ||||
|                         buff[i][particleBufIndex[i]].x    = new_x; | ||||
|                         buff[i][particleBufIndex[i]].y    = new_y; | ||||
|                         buff[i][particleBufIndex[i]].flag = true; | ||||
|                         ++particleBufIndex[i]; | ||||
|                     } | ||||
|                 } | ||||
|                 particletracer->particlePool[i].flag = false; | ||||
|                 particletracer->removedParticles++; | ||||
|             } | ||||
|  | ||||
|             int i_new = new_x / dx, j_new = new_y / dy; | ||||
|             int iOffset = particletracer->xOffset / dx, | ||||
|                 jOffset = particletracer->yOffset / dy; | ||||
|  | ||||
|             if (S(i_new - iOffset, j_new - jOffset) != FLUID) { | ||||
|                 particletracer->particlePool[i].flag = false; | ||||
|                 particletracer->removedParticles++; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #ifdef _MPI | ||||
|     for (int i = 0; i < particletracer->size; ++i) { | ||||
|         if (i != particletracer->rank) { | ||||
|             MPI_Send(buff[i], 100, particletracer->mpi_particle, i, 0, comm->comm); | ||||
|         } | ||||
|     } | ||||
|     for (int i = 0; i < particletracer->size; ++i) { | ||||
|         if (i != particletracer->rank) { | ||||
|             MPI_Recv(buff[i], | ||||
|                 100, | ||||
|                 particletracer->mpi_particle, | ||||
|                 i, | ||||
|                 0, | ||||
|                 comm->comm, | ||||
|                 MPI_STATUS_IGNORE); | ||||
|         } | ||||
|     } | ||||
|     for (int i = 0; i < particletracer->size; ++i) { | ||||
|         if (i != particletracer->rank) { | ||||
|             for (int j = 0; j < 100; ++j) { | ||||
|                 if (buff[i][j].flag == true) { | ||||
|                     particletracer->particlePool[particletracer->pointer].x = buff[i][j] | ||||
|                                                                                   .x; | ||||
|                     particletracer->particlePool[particletracer->pointer].y = buff[i][j] | ||||
|                                                                                   .y; | ||||
|                     particletracer->particlePool[particletracer->pointer].flag = true; | ||||
|                     ++(particletracer->pointer); | ||||
|                     ++(particletracer->totalParticles); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void freeParticles(ParticleTracer* particletracer) | ||||
| { | ||||
|     free(particletracer->particlePool); | ||||
|     free(particletracer->linSpaceLine); | ||||
|     free(particletracer->offset); | ||||
| } | ||||
|  | ||||
| void writeParticles(ParticleTracer* particletracer, Comm* comm) | ||||
| { | ||||
|     int collectedBuffIndex[particletracer->size]; | ||||
|  | ||||
| #ifdef _MPI | ||||
|  | ||||
|     MPI_Gather(&particletracer->totalParticles, | ||||
|         1, | ||||
|         MPI_INT, | ||||
|         collectedBuffIndex, | ||||
|         1, | ||||
|         MPI_INT, | ||||
|         0, | ||||
|         comm->comm); | ||||
|  | ||||
|     if (particletracer->rank != 0) { | ||||
|         Particle buff[particletracer->totalParticles]; | ||||
|         for (int i = 0; i < particletracer->totalParticles; ++i) { | ||||
|             buff[i].x    = particletracer->particlePool[i].x; | ||||
|             buff[i].y    = particletracer->particlePool[i].y; | ||||
|             buff[i].flag = particletracer->particlePool[i].flag; | ||||
|             // printf("Rank : %d sending to rank 0 X : %.2f, Y : %.2f with totalpt : | ||||
|             // %d\n", particletracer->rank, buff[i].x, buff[i].y, | ||||
|             // particletracer->totalParticles); | ||||
|         } | ||||
|         MPI_Send(buff, | ||||
|             particletracer->totalParticles, | ||||
|             particletracer->mpi_particle, | ||||
|             0, | ||||
|             1, | ||||
|             comm->comm); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     if (particletracer->rank == 0) { | ||||
|         char filename[50]; | ||||
|         FILE* fp; | ||||
|  | ||||
|         snprintf(filename, 50, "vis_files/particles_%d.dat", ts); | ||||
|         fp = fopen(filename, "w"); | ||||
|  | ||||
|         if (fp == NULL) { | ||||
|             printf("Error!\n"); | ||||
|             exit(EXIT_FAILURE); | ||||
|         } | ||||
|         // fprintf(fp, "# vtk DataFile Version 3.0\n"); | ||||
|         // fprintf(fp, "PAMPI cfd solver particle tracing file\n"); | ||||
|         // fprintf(fp, "ASCII\n"); | ||||
|  | ||||
|         // fprintf(fp, "DATASET UNSTRUCTURED_GRID\n"); | ||||
|         // fprintf(fp, "FIELD FieldData 2\n"); | ||||
|         // fprintf(fp, "TIME 1 1 double\n"); | ||||
|         // fprintf(fp, "%d\n", ts); | ||||
|         // fprintf(fp, "CYCLE 1 1 int\n"); | ||||
|         // fprintf(fp, "1\n"); | ||||
|  | ||||
|         int overallTotalParticles = sum(collectedBuffIndex, particletracer->size); | ||||
|  | ||||
|         // fprintf(fp, "POINTS %d float\n", overallTotalParticles); | ||||
|  | ||||
|         // printf("Total particles : %d\n", overallTotalParticles); | ||||
|  | ||||
| #ifdef _MPI | ||||
|         for (int i = 1; i < particletracer->size; ++i) { | ||||
|             Particle recvBuff[collectedBuffIndex[i]]; | ||||
|             MPI_Recv(&recvBuff, | ||||
|                 collectedBuffIndex[i], | ||||
|                 particletracer->mpi_particle, | ||||
|                 i, | ||||
|                 1, | ||||
|                 comm->comm, | ||||
|                 MPI_STATUS_IGNORE); | ||||
|  | ||||
|             for (int j = 0; j < collectedBuffIndex[i]; ++j) { | ||||
|                 double x = recvBuff[j].x; | ||||
|                 double y = recvBuff[j].y; | ||||
|                 fprintf(fp, "%f %f\n", x, y); | ||||
|                 // printf("Rank : 0 receiving from rank %d X : %.2f, Y : %.2f with totalpt | ||||
|                 // : %d\n", i, x, y, particletracer->totalParticles); | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|         for (int i = 0; i < particletracer->totalParticles; ++i) { | ||||
|             double x = particletracer->particlePool[i].x; | ||||
|             double y = particletracer->particlePool[i].y; | ||||
|             fprintf(fp, "%f %f\n", x, y); | ||||
|         } | ||||
|  | ||||
|         // fprintf(fp, "CELLS %d %d\n", overallTotalParticles, 2 * overallTotalParticles); | ||||
|  | ||||
|         // for (int i = 0; i < overallTotalParticles; ++i) | ||||
|         // { | ||||
|         //     fprintf(fp, "1 %d\n", i); | ||||
|         // } | ||||
|  | ||||
|         // fprintf(fp, "CELL_TYPES %d\n", overallTotalParticles); | ||||
|  | ||||
|         // for (int i = 0; i < overallTotalParticles; ++i) | ||||
|         // { | ||||
|         //     fprintf(fp, "1\n"); | ||||
|         // } | ||||
|  | ||||
|         fclose(fp); | ||||
|     } | ||||
|  | ||||
|     ++ts; | ||||
| } | ||||
|  | ||||
| void printParticleTracerParameters(ParticleTracer* particletracer) | ||||
| { | ||||
|     printf("Particle Tracing data:\n"); | ||||
|     printf("Rank : %d\n", particletracer->rank); | ||||
|     printf("\tNumber of particles : %d being injected for every period of %.2f\n", | ||||
|         particletracer->numberOfParticles, | ||||
|         particletracer->injectTimePeriod); | ||||
|     printf("\tstartTime : %.2f\n", particletracer->startTime); | ||||
|     printf("\t(Line along which the particles are to be injected) \n\tx1 : %.2f, y1 : " | ||||
|            "%.2f, x2 : %.2f, y2 : %.2f\n", | ||||
|         particletracer->x1, | ||||
|         particletracer->y1, | ||||
|         particletracer->x2, | ||||
|         particletracer->y2); | ||||
|     printf("\tPointer : %d, TotalParticles : %d\n", | ||||
|         particletracer->pointer, | ||||
|         particletracer->totalParticles); | ||||
|     printf("\tdt : %.2f, dx : %.2f, dy : %.2f\n", | ||||
|         particletracer->dt, | ||||
|         particletracer->dx, | ||||
|         particletracer->dy); | ||||
|     printf("\txOffset : %.2f, yOffset : %.2f\n", | ||||
|         particletracer->xOffset, | ||||
|         particletracer->yOffset); | ||||
|     printf("\txOffsetEnd : %.2f, yOffsetEnd : %.2f\n", | ||||
|         particletracer->xOffsetEnd, | ||||
|         particletracer->yOffsetEnd); | ||||
|     printf("\txLocal : %.2f, yLocal : %.2f\n", | ||||
|         particletracer->xLocal, | ||||
|         particletracer->yLocal); | ||||
| } | ||||
|  | ||||
| void trace(ParticleTracer* particletracer, Discretization* d, double time) | ||||
| { | ||||
|     if (time >= particletracer->startTime) { | ||||
|         if ((time - particletracer->lastInjectTime) >= particletracer->injectTimePeriod) { | ||||
|             injectParticles(particletracer); | ||||
|             particletracer->lastInjectTime = time; | ||||
|         } | ||||
|         if ((time - particletracer->lastWriteTime) >= particletracer->writeTimePeriod) { | ||||
|             writeParticles(particletracer, &d->comm); | ||||
|             particletracer->lastWriteTime = time; | ||||
|         } | ||||
|         advanceParticles(particletracer, d->u, d->v, d->grid.s, &d->comm, time); | ||||
|  | ||||
|         if (particletracer->removedParticles > (particletracer->totalParticles * 0.2)) { | ||||
|             compress(particletracer); | ||||
|         } | ||||
|  | ||||
|         particletracer->lastUpdateTime = time; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void compress(ParticleTracer* particletracer) | ||||
| { | ||||
|     Particle* memPool = particletracer->particlePool; | ||||
|     Particle tempPool[particletracer->totalParticles]; | ||||
|     int totalParticles = 0; | ||||
|  | ||||
|     printf("Performing compression ..."); | ||||
|  | ||||
|     for (int i = 0; i < particletracer->totalParticles; ++i) { | ||||
|         if (memPool[i].flag == true) { | ||||
|             tempPool[totalParticles].x    = memPool[i].x; | ||||
|             tempPool[totalParticles].y    = memPool[i].y; | ||||
|             tempPool[totalParticles].flag = memPool[i].flag; | ||||
|             ++totalParticles; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     printf(" remove %d particles\n", particletracer->totalParticles - totalParticles); | ||||
|  | ||||
|     particletracer->totalParticles   = totalParticles; | ||||
|     particletracer->removedParticles = 0; | ||||
|     particletracer->pointer          = totalParticles + 1; | ||||
|  | ||||
|     memcpy(particletracer->particlePool, tempPool, totalParticles * sizeof(Particle)); | ||||
| } | ||||
							
								
								
									
										64
									
								
								EnhancedSolver/2D-mpi/src/particletracing.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								EnhancedSolver/2D-mpi/src/particletracing.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| /* | ||||
|  * Copyright (C) 2022 NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __PARTICLETRACING_H_ | ||||
| #define __PARTICLETRACING_H_ | ||||
| #include "allocate.h" | ||||
| #include "parameter.h" | ||||
|  | ||||
| #include "solver.h" | ||||
| #include <mpi.h> | ||||
| #include <stdbool.h> | ||||
|  | ||||
| #define NDIMS 2 | ||||
|  | ||||
| typedef enum COORD { X = 0, Y, NCOORD } COORD; | ||||
|  | ||||
| typedef struct { | ||||
|     double x, y; | ||||
|     bool flag; | ||||
| } Particle; | ||||
|  | ||||
| typedef struct { | ||||
|     int numberOfParticles, removedParticles, totalParticles; | ||||
|     double startTime, injectTimePeriod, writeTimePeriod, lastInjectTime, lastUpdateTime, | ||||
|         lastWriteTime; | ||||
|  | ||||
|     int estimatedNumParticles; | ||||
|  | ||||
|     double dx, dy, dt; | ||||
|     Particle* linSpaceLine; | ||||
|     Particle* particlePool; | ||||
|  | ||||
|     int pointer; | ||||
|  | ||||
|     double imax, jmax, xlength, ylength, imaxLocal, jmaxLocal; | ||||
|  | ||||
|     double x1, y1, x2, y2; | ||||
|  | ||||
|     int size, rank; | ||||
|      | ||||
| #ifdef _MPI | ||||
|     MPI_Datatype mpi_particle; | ||||
| #endif | ||||
|  | ||||
|     double xLocal, yLocal, xOffset, yOffset, xOffsetEnd, yOffsetEnd; | ||||
|  | ||||
|     double* offset; | ||||
|  | ||||
| } ParticleTracer; | ||||
|  | ||||
| extern void initParticleTracer(ParticleTracer*, Discretization*, Parameter*); | ||||
| extern void injectParticles(ParticleTracer*); | ||||
| extern void advanceParticles(ParticleTracer*, double*, double*, double*, Comm*, double); | ||||
| extern void freeParticles(ParticleTracer*); | ||||
| extern void writeParticles(ParticleTracer*, Comm*); | ||||
| extern void printParticleTracerParameters(ParticleTracer*); | ||||
| extern void printParticles(ParticleTracer*); | ||||
| extern void trace(ParticleTracer*, Discretization*, double); | ||||
| extern void compress(ParticleTracer*); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										51
									
								
								EnhancedSolver/2D-mpi/src/progress.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								EnhancedSolver/2D-mpi/src/progress.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <math.h> | ||||
| #include <mpi.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "progress.h" | ||||
|  | ||||
| static double _end; | ||||
| static int _current; | ||||
|  | ||||
| void initProgress(double end) | ||||
| { | ||||
|     _end     = end; | ||||
|     _current = 0; | ||||
|  | ||||
|     printf("[          ]"); | ||||
|     fflush(stdout); | ||||
| } | ||||
|  | ||||
| void printProgress(double current) | ||||
| { | ||||
|     int new = (int)rint((current / _end) * 10.0); | ||||
|  | ||||
|     if (new > _current) { | ||||
|         char progress[11]; | ||||
|         _current    = new; | ||||
|         progress[0] = 0; | ||||
|  | ||||
|         for (int i = 0; i < 10; i++) { | ||||
|             if (i < _current) { | ||||
|                 sprintf(progress + strlen(progress), "#"); | ||||
|             } else { | ||||
|                 sprintf(progress + strlen(progress), " "); | ||||
|             } | ||||
|         } | ||||
|         printf("\r[%s]", progress); | ||||
|     } | ||||
|     fflush(stdout); | ||||
| } | ||||
|  | ||||
| void stopProgress() | ||||
| { | ||||
|     printf("\n"); | ||||
|     fflush(stdout); | ||||
| } | ||||
							
								
								
									
										14
									
								
								EnhancedSolver/2D-mpi/src/progress.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								EnhancedSolver/2D-mpi/src/progress.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __PROGRESS_H_ | ||||
| #define __PROGRESS_H_ | ||||
|  | ||||
| extern void initProgress(double); | ||||
| extern void printProgress(double); | ||||
| extern void stopProgress(); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										324
									
								
								EnhancedSolver/2D-mpi/src/solver-mg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								EnhancedSolver/2D-mpi/src/solver-mg.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,324 @@ | ||||
| /* | ||||
|  * Copyright (C) NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "allocate.h" | ||||
| #include "solver.h" | ||||
| #include "util.h" | ||||
|  | ||||
| #define FINEST_LEVEL   0 | ||||
| #define COARSEST_LEVEL (s->levels - 1) | ||||
|  | ||||
| #define E(i, j)   e[(j) * (imaxLocal + 2) + (i)] | ||||
| #define R(i, j)   r[(j) * (imaxLocal + 2) + (i)] | ||||
| #define OLD(i, j) old[(j) * (imaxLocal + 2) + (i)] | ||||
|  | ||||
| void printSolver(Solver* s, double* grid, char* gridname) | ||||
| { | ||||
|     if (0 == s->comm->rank) printf("Grid name : %s", gridname); | ||||
|     int imaxLocal = s->comm->imaxLocal; | ||||
|     int jmaxLocal = s->comm->jmaxLocal; | ||||
|  | ||||
|     for (int i = 0; i < s->comm->size; i++) { | ||||
|         if (i == s->comm->rank) { | ||||
|             sleep(1 * s->comm->rank); | ||||
|             printf("### RANK %d LVL " | ||||
|                    "###################################################### #\n ", | ||||
|                 s->comm->rank); | ||||
|             for (int j = 0; j < jmaxLocal + 2; j++) { | ||||
|                 printf("%02d: ", j); | ||||
|                 for (int i = 0; i < imaxLocal + 2; i++) { | ||||
|                     printf("%2.2f  ", grid[j * (imaxLocal + 2) + i]); | ||||
|                 } | ||||
|                 printf("\n"); | ||||
|             } | ||||
|             fflush(stdout); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void restrictMG(Solver* s, int level, Comm* comm) | ||||
| { | ||||
|     int imaxLocal = comm->imaxLocal; | ||||
|     int jmaxLocal = comm->jmaxLocal; | ||||
|  | ||||
|     double* r   = s->r[level + 1]; | ||||
|     double* old = s->r[level]; | ||||
|  | ||||
| #ifdef _MPI | ||||
|     commExchange(comm, old); | ||||
| #endif | ||||
|  | ||||
|     for (int j = 1; j < (jmaxLocal / 2) + 1; j++) { | ||||
|         for (int i = 1; i < (imaxLocal / 2) + 1; i++) { | ||||
|             R(i, j) = (OLD(2 * i - 1, 2 * j - 1) + OLD(2 * i, 2 * j - 1) * 2 + | ||||
|                           OLD(2 * i + 1, 2 * j - 1) + OLD(2 * i - 1, 2 * j) * 2 + | ||||
|                           OLD(2 * i, 2 * j) * 4 + OLD(2 * i + 1, 2 * j) * 2 + | ||||
|                           OLD(2 * i - 1, 2 * j + 1) + OLD(2 * i, 2 * j + 1) * 2 + | ||||
|                           OLD(2 * i + 1, 2 * j + 1)) / | ||||
|                       16.0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void prolongate(Solver* s, int level, Comm* comm) | ||||
| { | ||||
|     int imaxLocal = comm->imaxLocal; | ||||
|     int jmaxLocal = comm->jmaxLocal; | ||||
|  | ||||
|     double* old = s->r[level + 1]; | ||||
|     double* e   = s->r[level]; | ||||
|  | ||||
|     for (int j = 2; j < jmaxLocal + 1; j += 2) { | ||||
|         for (int i = 2; i < imaxLocal + 1; i += 2) { | ||||
|             E(i, j) = OLD(i / 2, j / 2); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void correct(Solver* s, double* p, int level, Comm* comm) | ||||
| { | ||||
|     double* e     = s->e[level]; | ||||
|     int imaxLocal = comm->imaxLocal; | ||||
|     int jmaxLocal = comm->jmaxLocal; | ||||
|  | ||||
|     for (int j = 1; j < jmaxLocal + 1; ++j) { | ||||
|         for (int i = 1; i < imaxLocal + 1; ++i) { | ||||
|             P(i, j) += E(i, j); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void setBoundaryCondition(Solver* s, double* p, int imaxLocal, int jmaxLocal) | ||||
| { | ||||
| #ifdef _MPI | ||||
|     if (commIsBoundary(s->comm, B)) { // set bottom bc | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             P(i, 0) = P(i, 1); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(s->comm, T)) { // set top bc | ||||
|         for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|             P(i, jmaxLocal + 1) = P(i, jmaxLocal); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(s->comm, L)) { // set left bc | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             P(0, j) = P(1, j); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (commIsBoundary(s->comm, R)) { // set right bc | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             P(imaxLocal + 1, j) = P(imaxLocal, j); | ||||
|         } | ||||
|     } | ||||
| #else | ||||
|     for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|         P(i, 0)             = P(i, 1); | ||||
|         P(i, jmaxLocal + 1) = P(i, jmaxLocal); | ||||
|     } | ||||
|  | ||||
|     for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|         P(0, j)             = P(1, j); | ||||
|         P(imaxLocal + 1, j) = P(imaxLocal, j); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static double smooth(Solver* s, double* p, double* rhs, int level, Comm* comm) | ||||
| { | ||||
|     int imaxLocal = comm->imaxLocal; | ||||
|     int jmaxLocal = comm->jmaxLocal; | ||||
|  | ||||
|     int imax = s->grid->imax; | ||||
|     int jmax = s->grid->jmax; | ||||
|  | ||||
|     double dx2  = s->grid->dx * s->grid->dx; | ||||
|     double dy2  = s->grid->dy * s->grid->dy; | ||||
|     double idx2 = 1.0 / dx2; | ||||
|     double idy2 = 1.0 / dy2; | ||||
|  | ||||
|     double factor = s->omega * 0.5 * (dx2 * dy2) / (dx2 + dy2); | ||||
|     double* r     = s->r[level]; | ||||
|  | ||||
|     double res = 1.0; | ||||
|     int pass, jsw, isw; | ||||
|  | ||||
|     jsw = 1; | ||||
|  | ||||
|     for (pass = 0; pass < 2; pass++) { | ||||
|         isw = jsw; | ||||
|  | ||||
| #ifdef _MPI | ||||
|         commExchange(comm, p); | ||||
| #endif | ||||
|  | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             for (int i = isw; i < imaxLocal + 1; i += 2) { | ||||
|  | ||||
|                 P(i, j) -= factor * | ||||
|                            (RHS(i, j) - | ||||
|                                ((P(i + 1, j) - 2.0 * P(i, j) + P(i - 1, j)) * idx2 + | ||||
|                                    (P(i, j + 1) - 2.0 * P(i, j) + P(i, j - 1)) * idy2)); | ||||
|             } | ||||
|             isw = 3 - isw; | ||||
|         } | ||||
|         jsw = 3 - jsw; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static double calculateResidual(Solver* s, double* p, double* rhs, int level, Comm* comm) | ||||
| { | ||||
|     int imax      = s->grid->imax; | ||||
|     int jmax      = s->grid->jmax; | ||||
|     int imaxLocal = comm->imaxLocal; | ||||
|     int jmaxLocal = comm->jmaxLocal; | ||||
|  | ||||
|     double dx2    = s->grid->dx * s->grid->dx; | ||||
|     double dy2    = s->grid->dy * s->grid->dy; | ||||
|     double idx2   = 1.0 / dx2; | ||||
|     double idy2   = 1.0 / dy2; | ||||
|     double factor = s->omega * 0.5 * (dx2 * dy2) / (dx2 + dy2); | ||||
|     double* r     = s->r[level]; | ||||
|     double res    = 1.0; | ||||
|     int pass, jsw, isw; | ||||
|  | ||||
|     jsw = 1; | ||||
|  | ||||
|     for (pass = 0; pass < 2; pass++) { | ||||
|         isw = jsw; | ||||
|  | ||||
| #ifdef _MPI | ||||
|         commExchange(comm, p); | ||||
| #endif | ||||
|  | ||||
|         for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|             for (int i = isw; i < imaxLocal + 1; i += 2) { | ||||
|  | ||||
|                 R(i, j) = RHS(i, j) - | ||||
|                           ((P(i + 1, j) - 2.0 * P(i, j) + P(i - 1, j)) * idx2 + | ||||
|                               (P(i, j + 1) - 2.0 * P(i, j) + P(i, j - 1)) * idy2); | ||||
|  | ||||
|                 res += (R(i, j) * R(i, j)); | ||||
|             } | ||||
|             isw = 3 - isw; | ||||
|         } | ||||
|         jsw = 3 - jsw; | ||||
|     } | ||||
|  | ||||
| #ifdef _MPI | ||||
|     commReduction(&res, SUM); | ||||
| #endif | ||||
|  | ||||
|     res = res / (double)(imax * jmax); | ||||
| #ifdef DEBUG | ||||
|     if (commIsMaster(s->comm)) { | ||||
|         printf("%d Residuum: %e\n", it, res); | ||||
|     } | ||||
| #endif | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static double multiGrid(Solver* s, double* p, double* rhs, int level, Comm* comm) | ||||
| { | ||||
|     double res = 0.0; | ||||
|  | ||||
|     // coarsest level | ||||
|     if (level == COARSEST_LEVEL) { | ||||
|         for (int i = 0; i < 5; i++) { | ||||
|             smooth(s, p, rhs, level, comm); | ||||
|         } | ||||
|         return res; | ||||
|     } | ||||
|  | ||||
|     // pre-smoothing | ||||
|     for (int i = 0; i < s->presmooth; i++) { | ||||
|         smooth(s, p, rhs, level, comm); | ||||
|  | ||||
|         if (level == FINEST_LEVEL) | ||||
|             setBoundaryCondition(s, p, comm->imaxLocal, comm->jmaxLocal); | ||||
|     } | ||||
|  | ||||
|     // calculate residuals | ||||
|     res = calculateResidual(s, p, rhs, level, comm); | ||||
|  | ||||
|     // restrict | ||||
|     restrictMG(s, level, comm); | ||||
|  | ||||
|     Comm newcomm; | ||||
|     commUpdateDatatypes(s->comm, &newcomm, comm->imaxLocal / 2, comm->jmaxLocal / 2); | ||||
|  | ||||
|     // MGSolver on residual and error. | ||||
|     multiGrid(s, s->e[level + 1], s->r[level + 1], level + 1, &newcomm); | ||||
|  | ||||
|     commFreeCommunicator(&newcomm); | ||||
|  | ||||
|     // prolongate | ||||
|     prolongate(s, level, comm); | ||||
|  | ||||
|     // correct p on finer level using residual | ||||
|     correct(s, p, level, comm); | ||||
|  | ||||
|     if (level == FINEST_LEVEL) | ||||
|         setBoundaryCondition(s, p, comm->imaxLocal, comm->jmaxLocal); | ||||
|  | ||||
|     // post-smoothing | ||||
|     for (int i = 0; i < s->postsmooth; i++) { | ||||
|         smooth(s, p, rhs, level, comm); | ||||
|         if (level == FINEST_LEVEL) | ||||
|             setBoundaryCondition(s, p, comm->imaxLocal, comm->jmaxLocal); | ||||
|     } | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| void initSolver(Solver* s, Discretization* d, Parameter* p) | ||||
| { | ||||
|     s->eps        = p->eps; | ||||
|     s->omega      = p->omg; | ||||
|     s->itermax    = p->itermax; | ||||
|     s->levels     = p->levels; | ||||
|     s->grid       = &d->grid; | ||||
|     s->comm       = &d->comm; | ||||
|     s->presmooth  = p->presmooth; | ||||
|     s->postsmooth = p->postsmooth; | ||||
|  | ||||
|     int imax   = s->grid->imax; | ||||
|     int jmax   = s->grid->jmax; | ||||
|     int levels = s->levels; | ||||
|     printf("Using Multigrid solver with %d levels\n", levels); | ||||
|  | ||||
|     s->r = malloc(levels * sizeof(double*)); | ||||
|     s->e = malloc(levels * sizeof(double*)); | ||||
|  | ||||
|     size_t size = (imax + 2) * (jmax + 2) * sizeof(double); | ||||
|  | ||||
|     for (int j = 0; j < levels; j++) { | ||||
|         s->r[j] = allocate(64, size); | ||||
|         s->e[j] = allocate(64, size); | ||||
|  | ||||
|         for (int i = 0; i < (imax + 2) * (jmax + 2); i++) { | ||||
|             s->r[j][i] = 0.0; | ||||
|             s->e[j][i] = 0.0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void solve(Solver* s, double* p, double* rhs) | ||||
| { | ||||
|     double res = multiGrid(s, p, rhs, 0, s->comm); | ||||
|  | ||||
| #ifdef VERBOSE | ||||
|     if (commIsMaster(s->comm)) { | ||||
|         printf("Residuum: %.6f\n", res); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
							
								
								
									
										129
									
								
								EnhancedSolver/2D-mpi/src/solver-rb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								EnhancedSolver/2D-mpi/src/solver-rb.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <math.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "allocate.h" | ||||
| #include "comm.h" | ||||
| #include "discretization.h" | ||||
| #include "parameter.h" | ||||
| #include "solver.h" | ||||
| #include "util.h" | ||||
|  | ||||
| void printSolver(Solver* s, double* grid, char* gridname) | ||||
| { | ||||
|     printf("Grid name : %s", gridname); | ||||
|     int imaxLocal = s->comm->imaxLocal; | ||||
|     int jmaxLocal = s->comm->jmaxLocal; | ||||
|  | ||||
|     for (int i = 0; i < s->comm->size; i++) { | ||||
|         if (i == s->comm->rank) { | ||||
|             sleep(1 * s->comm->rank); | ||||
|             printf("### RANK %d LVL " | ||||
|                    "###################################################### #\n ", | ||||
|                 s->comm->rank); | ||||
|             for (int j = 0; j < jmaxLocal + 2; j++) { | ||||
|                 printf("%02d: ", j); | ||||
|                 for (int i = 0; i < imaxLocal + 2; i++) { | ||||
|                     printf("%2.2f  ", grid[j * (imaxLocal + 2) + i]); | ||||
|                 } | ||||
|                 printf("\n"); | ||||
|             } | ||||
|             fflush(stdout); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| void initSolver(Solver* s, Discretization* d, Parameter* p) | ||||
| { | ||||
|     s->grid    = &d->grid; | ||||
|     s->eps     = p->eps; | ||||
|     s->omega   = p->omg; | ||||
|     s->itermax = p->itermax; | ||||
|     s->comm    = &d->comm; | ||||
| } | ||||
|  | ||||
| void solve(Solver* s, double* p, double* rhs) | ||||
| { | ||||
|     int imax      = s->grid->imax; | ||||
|     int jmax      = s->grid->jmax; | ||||
|     int imaxLocal = s->comm->imaxLocal; | ||||
|     int jmaxLocal = s->comm->jmaxLocal; | ||||
|     double eps    = s->eps; | ||||
|     int itermax   = s->itermax; | ||||
|     double dx2    = s->grid->dx * s->grid->dx; | ||||
|     double dy2    = s->grid->dy * s->grid->dy; | ||||
|     double idx2   = 1.0 / dx2; | ||||
|     double idy2   = 1.0 / dy2; | ||||
|     double factor = s->omega * 0.5 * (dx2 * dy2) / (dx2 + dy2); | ||||
|     double epssq  = eps * eps; | ||||
|     int pass, jsw, isw; | ||||
|     int it     = 0; | ||||
|     double res = 1.0; | ||||
|  | ||||
|     while ((res >= epssq) && (it < itermax)) { | ||||
|         jsw = 1; | ||||
|         for (pass = 0; pass < 2; pass++) { | ||||
|             isw = jsw; | ||||
|             commExchange(s->comm, p); | ||||
|  | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 for (int i = isw; i < imaxLocal + 1; i += 2) { | ||||
|  | ||||
|                     double r = RHS(i, j) - | ||||
|                                ((P(i + 1, j) - 2.0 * P(i, j) + P(i - 1, j)) * idx2 + | ||||
|                                    (P(i, j + 1) - 2.0 * P(i, j) + P(i, j - 1)) * idy2); | ||||
|  | ||||
|                     P(i, j) -= (factor * r); | ||||
|                     res += (r * r); | ||||
|                 } | ||||
|                 isw = 3 - isw; | ||||
|             } | ||||
|             jsw = 3 - jsw; | ||||
|         } | ||||
|  | ||||
|         if (commIsBoundary(s->comm, B)) { // set bottom bc | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 P(i, 0) = P(i, 1); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (commIsBoundary(s->comm, T)) { // set top bc | ||||
|             for (int i = 1; i < imaxLocal + 1; i++) { | ||||
|                 P(i, jmaxLocal + 1) = P(i, jmaxLocal); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (commIsBoundary(s->comm, L)) { // set left bc | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 P(0, j) = P(1, j); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (commIsBoundary(s->comm, R)) { // set right bc | ||||
|             for (int j = 1; j < jmaxLocal + 1; j++) { | ||||
|                 P(imaxLocal + 1, j) = P(imaxLocal, j); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         commReduction(&res, SUM); | ||||
|         res = res / (double)(imax * jmax); | ||||
| #ifdef DEBUG | ||||
|         if (commIsMaster(s->comm)) { | ||||
|             printf("%d Residuum: %e\n", it, res); | ||||
|         } | ||||
| #endif | ||||
|         it++; | ||||
|     } | ||||
|  | ||||
| #ifdef VERBOSE | ||||
|     if (commIsMaster(s->comm)) { | ||||
|         printf("Solver took %d iterations to reach %f\n", it, sqrt(res)); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
							
								
								
									
										30
									
								
								EnhancedSolver/2D-mpi/src/solver.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								EnhancedSolver/2D-mpi/src/solver.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. This file is part of nusif-solver. | ||||
|  * Use of this source code is governed by a MIT style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __SOLVER_H_ | ||||
| #define __SOLVER_H_ | ||||
| #include "comm.h" | ||||
| #include "discretization.h" | ||||
| #include "grid.h" | ||||
| #include "mpi.h" | ||||
| #include "parameter.h" | ||||
|  | ||||
| typedef struct { | ||||
|     /* geometry and grid information */ | ||||
|     Grid* grid; | ||||
|     /* parameters */ | ||||
|     double eps, omega; | ||||
|     int itermax; | ||||
|     int levels, presmooth, postsmooth; | ||||
|     double **r, **e; | ||||
|     /* communication */ | ||||
|     Comm* comm; | ||||
| } Solver; | ||||
|  | ||||
| void initSolver(Solver*, Discretization*, Parameter*); | ||||
| void solve(Solver*, double*, double*); | ||||
| void printSolver(Solver* , double*, char*); | ||||
| #endif | ||||
							
								
								
									
										22
									
								
								EnhancedSolver/2D-mpi/src/timing.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								EnhancedSolver/2D-mpi/src/timing.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <time.h> | ||||
|  | ||||
| double getTimeStamp(void) | ||||
| { | ||||
|     struct timespec ts; | ||||
|     clock_gettime(CLOCK_MONOTONIC, &ts); | ||||
|     return (double)ts.tv_sec + (double)ts.tv_nsec * 1.e-9; | ||||
| } | ||||
|  | ||||
| double getTimeResolution(void) | ||||
| { | ||||
|     struct timespec ts; | ||||
|     clock_getres(CLOCK_MONOTONIC, &ts); | ||||
|     return (double)ts.tv_sec + (double)ts.tv_nsec * 1.e-9; | ||||
| } | ||||
							
								
								
									
										13
									
								
								EnhancedSolver/2D-mpi/src/timing.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								EnhancedSolver/2D-mpi/src/timing.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __TIMING_H_ | ||||
| #define __TIMING_H_ | ||||
|  | ||||
| extern double getTimeStamp(void); | ||||
| extern double getTimeResolution(void); | ||||
|  | ||||
| #endif // __TIMING_H_ | ||||
							
								
								
									
										30
									
								
								EnhancedSolver/2D-mpi/src/util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								EnhancedSolver/2D-mpi/src/util.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg. | ||||
|  * All rights reserved. | ||||
|  * Use of this source code is governed by a MIT-style | ||||
|  * license that can be found in the LICENSE file. | ||||
|  */ | ||||
| #ifndef __UTIL_H_ | ||||
| #define __UTIL_H_ | ||||
| #define HLINE                                                                            \ | ||||
|     "----------------------------------------------------------------------------\n" | ||||
|  | ||||
| #ifndef MIN | ||||
| #define MIN(x, y) ((x) < (y) ? (x) : (y)) | ||||
| #endif | ||||
| #ifndef MAX | ||||
| #define MAX(x, y) ((x) > (y) ? (x) : (y)) | ||||
| #endif | ||||
| #ifndef ABS | ||||
| #define ABS(a) ((a) >= 0 ? (a) : -(a)) | ||||
| #endif | ||||
|  | ||||
| #define P(i, j)   p[(j) * (imaxLocal + 2) + (i)] | ||||
| #define F(i, j)   f[(j) * (imaxLocal + 2) + (i)] | ||||
| #define G(i, j)   g[(j) * (imaxLocal + 2) + (i)] | ||||
| #define U(i, j)   u[(j) * (imaxLocal + 2) + (i)] | ||||
| #define V(i, j)   v[(j) * (imaxLocal + 2) + (i)] | ||||
| #define S(i, j)   s[(j) * (imaxLocal + 2) + (i)] | ||||
| #define RHS(i, j) rhs[(j) * (imaxLocal + 2) + (i)] | ||||
|  | ||||
| #endif // __UTIL_H_ | ||||
							
								
								
									
										7
									
								
								EnhancedSolver/2D-mpi/surface.plot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								EnhancedSolver/2D-mpi/surface.plot
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| set terminal png size 1024,768 enhanced font ,12 | ||||
| set output 'p.png' | ||||
| set datafile separator whitespace | ||||
|  | ||||
| set grid | ||||
| set hidden3d | ||||
| splot 'pressure.dat' using 1:2:3 with lines | ||||
							
								
								
									
										6
									
								
								EnhancedSolver/2D-mpi/vector.plot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								EnhancedSolver/2D-mpi/vector.plot
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| set terminal png size 3600,1400 enhanced font ,12 | ||||
| set output 'velocity.png' | ||||
| set datafile separator whitespace | ||||
| set size ratio -1 | ||||
|  | ||||
| plot 'velocity.dat' using 1:2:3:4:5 with vectors filled head size 0.01,20,60 lc palette | ||||
							
								
								
									
										10
									
								
								EnhancedSolver/2D-mpi/vis_files/animate.plot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								EnhancedSolver/2D-mpi/vis_files/animate.plot
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| unset border; unset tics; unset key; | ||||
| set term gif animate delay 30 | ||||
| set output "trace.gif" | ||||
| set xrange [0:1] | ||||
| set yrange [0:1] | ||||
|  | ||||
| do for [ts=0:120] { | ||||
|     plot "particles_".ts.".dat" with points pointtype 7 | ||||
| } | ||||
| unset output | ||||
							
								
								
									
										14
									
								
								EnhancedSolver/2D-mpi/vis_files/backstep_animate.plot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								EnhancedSolver/2D-mpi/vis_files/backstep_animate.plot
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| unset border; unset tics; unset key; | ||||
| set term gif animate delay 10 | ||||
| set output "trace.gif" | ||||
| set xrange [0:7] | ||||
| set yrange [0:1.5] | ||||
| set size ratio -1 | ||||
|  | ||||
| set object 1 rect from 0.0,0.0 to 1.0,0.5 lw 5 | ||||
|  | ||||
|  | ||||
| do for [ts=0:300] { | ||||
|     plot "particles_".ts.".dat" with points pointtype 7 | ||||
| } | ||||
| unset output | ||||
							
								
								
									
										13
									
								
								EnhancedSolver/2D-mpi/vis_files/karman_animate.plot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								EnhancedSolver/2D-mpi/vis_files/karman_animate.plot
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| unset border; unset tics; unset key; | ||||
| set term gif animate delay 10 | ||||
| set output "trace.gif" | ||||
| set xrange [0:30] | ||||
| set yrange [0:8] | ||||
| set size ratio -1 | ||||
| set object 1 circle front at 5.0,4.0 size 1.0 fillcolor rgb "black" lw 2 | ||||
|  | ||||
|  | ||||
| do for [ts=0:500] { | ||||
|     plot "particles_".ts.".dat" with points pointtype 7 pointsize 0.3 | ||||
| } | ||||
| unset output | ||||
| @@ -70,6 +70,18 @@ format: | ||||
| 	done | ||||
| 	@echo "Done" | ||||
|  | ||||
| vis: | ||||
| 	$(info ===>  GENERATE VISUALIZATION) | ||||
| 	@gnuplot -e "filename='pressure.dat'" ./surface.plot | ||||
| 	@gnuplot -e "filename='velocity.dat'" ./vector.plot | ||||
|  | ||||
| vis_clean: | ||||
| 	$(info ===>  CLEAN VISUALIZATION) | ||||
| 	@rm -f *.dat | ||||
| 	@rm -f *.png | ||||
| 	@rm -f ./vis_files/*.dat | ||||
| 	@rm -f ./vis_files/*.gif | ||||
|  | ||||
| $(BUILD_DIR): | ||||
| 	@mkdir $(BUILD_DIR) | ||||
|  | ||||
|   | ||||
| @@ -15,7 +15,7 @@ bcRight    3			# | ||||
| gx    0.0      # Body forces (e.g. gravity) | ||||
| gy    0.0      # | ||||
|  | ||||
| re    36500.0	   # Reynolds number | ||||
| re    20000.0	   # Reynolds number | ||||
|  | ||||
| u_init    1.0      # initial value for velocity in x-direction | ||||
| v_init    0.0      # initial value for velocity in y-direction | ||||
| @@ -45,11 +45,18 @@ rho      0.52 | ||||
| omg      1.8       # relaxation parameter for SOR iteration | ||||
| gamma    0.9       # upwind differencing factor gamma | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        3         # Multigrid levels | ||||
| presmooth     5         # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|  | ||||
| numberOfParticles   200 | ||||
| startTime           100 | ||||
| startTime           10 | ||||
| injectTimePeriod    1.0 | ||||
| writeTimePeriod     0.5 | ||||
|  | ||||
|   | ||||
| @@ -44,7 +44,13 @@ eps      0.0001   # stopping tolerance for pressure iteration | ||||
| rho      0.52 | ||||
| omg      1.8       # relaxation parameter for SOR iteration | ||||
| gamma    0.9       # upwind differencing factor gamma | ||||
| levels   5         # Multigrid levels | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        3         # Multigrid levels | ||||
| presmooth     5         # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| # Supported: GCC, CLANG, ICC | ||||
| TAG ?= CLANG | ||||
| TAG ?= ICC | ||||
| ENABLE_OPENMP ?= false | ||||
| # Supported: sor, rb, mg | ||||
| SOLVER ?= mg | ||||
|   | ||||
| @@ -44,7 +44,13 @@ eps      0.001		# stopping tolerance for pressure iteration | ||||
| rho      0.5 | ||||
| omg      1.8		# relaxation parameter for SOR iteration | ||||
| gamma    0.9		# upwind differencing factor gamma | ||||
| levels   5         # Multigrid levels | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        3         # Multigrid levels | ||||
| presmooth     10        # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|   | ||||
| @@ -44,13 +44,19 @@ eps      0.001   # stopping tolerance for pressure iteration | ||||
| rho      0.52 | ||||
| omg      1.75      # relaxation parameter for SOR iteration | ||||
| gamma    0.9       # upwind differencing factor gamma | ||||
| levels   5         # Multigrid levels | ||||
|  | ||||
| # Multigrid data: | ||||
| # --------- | ||||
|  | ||||
| levels        3         # Multigrid levels | ||||
| presmooth     5         # Pre-smoothning iterations | ||||
| postsmooth    5         # Post-smoothning iterations | ||||
|  | ||||
| # Particle Tracing Data: | ||||
| # ----------------------- | ||||
|  | ||||
| numberOfParticles   200 | ||||
| startTime           201 | ||||
| startTime           50 | ||||
| injectTimePeriod    1.0 | ||||
| writeTimePeriod     0.5 | ||||
|  | ||||
|   | ||||
| @@ -98,7 +98,7 @@ static void advanceParticles( | ||||
|             if (!gridIsFluid(p->grid, newI, newJ)) { | ||||
|                 p->particlePool[i].flag = false; | ||||
|                 p->removedParticles++; | ||||
|                 printf("Forbidden movement of particle into obstacle!\n"); | ||||
|                 // printf("Forbidden movement of particle into obstacle!\n"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
							
								
								
									
										10
									
								
								EnhancedSolver/2D-seq/vis_files/canal_animate.plot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								EnhancedSolver/2D-seq/vis_files/canal_animate.plot
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| unset border; unset tics; unset key; | ||||
| set term gif animate delay 30 | ||||
| set output "trace.gif" | ||||
| set xrange [0:30] | ||||
| set yrange [0:4] | ||||
|  | ||||
| do for [ts=0:120] { | ||||
|     plot "particles_".ts.".dat" with points pointtype 7 | ||||
| } | ||||
| unset output | ||||
		Reference in New Issue
	
	Block a user