Sheet 7
This commit is contained in:
parent
33c18c8808
commit
4c92446409
74 changed files with 169041 additions and 0 deletions
17
sheet7/E1234/.vscode/c_cpp_properties.json
vendored
Normal file
17
sheet7/E1234/.vscode/c_cpp_properties.json
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/usr/lib/x86_64-linux-gnu/openmpi/include"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
2877
sheet7/E1234/Doxyfile
Normal file
2877
sheet7/E1234/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
23
sheet7/E1234/Makefile
Normal file
23
sheet7/E1234/Makefile
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#
|
||||||
|
# Compile with
|
||||||
|
# make 2>&1 | grep -v openmpi
|
||||||
|
# to avoid warnings caused by OpenMPI
|
||||||
|
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
MAIN = main
|
||||||
|
SOURCES = ${MAIN}.cpp greetings.cpp
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = ${MAIN}.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
LINKFLAGS +=
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
85
sheet7/E1234/greetings.cpp
Normal file
85
sheet7/E1234/greetings.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#include "greetings.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mpi.h> // MPI
|
||||||
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// see http://www.open-mpi.org/doc/current
|
||||||
|
// for details on MPI functions
|
||||||
|
|
||||||
|
void greetings(MPI_Comm const &icomm)
|
||||||
|
{
|
||||||
|
int myrank, numprocs;
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs); // #MPI processes
|
||||||
|
char *name = new char [MPI_MAX_PROCESSOR_NAME],
|
||||||
|
*chbuf = new char [MPI_MAX_PROCESSOR_NAME];
|
||||||
|
|
||||||
|
int reslen, ierr;
|
||||||
|
MPI_Get_processor_name( name, &reslen);
|
||||||
|
|
||||||
|
if (0==myrank) {
|
||||||
|
cout << " " << myrank << " runs on " << name << endl;
|
||||||
|
for (int i = 1; i < numprocs; ++i) {
|
||||||
|
MPI_Status stat;
|
||||||
|
stat.MPI_ERROR = 0; // M U S T be initialized!!
|
||||||
|
|
||||||
|
ierr = MPI_Recv(chbuf, MPI_MAX_PROCESSOR_NAME, MPI_CHAR, i, MPI_ANY_TAG, icomm, &stat);
|
||||||
|
assert(0==ierr);
|
||||||
|
|
||||||
|
cout << " " << stat.MPI_SOURCE << " runs on " << chbuf;
|
||||||
|
int count;
|
||||||
|
MPI_Get_count(&stat, MPI_CHAR, &count); // size of received data
|
||||||
|
cout << " (length: " << count << " )" << endl;
|
||||||
|
// stat.Get_error() // Error code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int dest = 0;
|
||||||
|
ierr = MPI_Send(name, strlen(name) + 1, MPI_CHAR, dest, myrank, icomm);
|
||||||
|
assert(0==ierr);
|
||||||
|
}
|
||||||
|
delete [] chbuf;
|
||||||
|
delete [] name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void greetings_cpp(MPI_Comm const &icomm)
|
||||||
|
{
|
||||||
|
int myrank, numprocs;
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs); // #MPI processes
|
||||||
|
string name(MPI_MAX_PROCESSOR_NAME,'#'), // C++
|
||||||
|
recvbuf(MPI_MAX_PROCESSOR_NAME,'#'); // C++: receive buffer, don't change size
|
||||||
|
|
||||||
|
int reslen, ierr;
|
||||||
|
MPI_Get_processor_name(name.data(), &reslen);
|
||||||
|
name.resize(reslen); // C++
|
||||||
|
|
||||||
|
if (0==myrank) {
|
||||||
|
cout << " " << myrank << " runs on " << name << endl;
|
||||||
|
for (int i = 1; i < numprocs; ++i) {
|
||||||
|
MPI_Status stat;
|
||||||
|
stat.MPI_ERROR = 0; // M U S T be initialized!!
|
||||||
|
|
||||||
|
ierr = MPI_Recv(recvbuf.data(), MPI_MAX_PROCESSOR_NAME, MPI_CHAR, i, MPI_ANY_TAG, icomm, &stat);
|
||||||
|
assert(0==ierr);
|
||||||
|
|
||||||
|
int count;
|
||||||
|
MPI_Get_count(&stat, MPI_CHAR, &count); // size of received data
|
||||||
|
string const chbuf(recvbuf,0,count); // C++
|
||||||
|
cout << " " << stat.MPI_SOURCE << " runs on " << chbuf;
|
||||||
|
cout << " (length: " << count << " )" << endl;
|
||||||
|
// stat.Get_error() // Error code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int dest = 0;
|
||||||
|
ierr = MPI_Send(name.data(), name.size(), MPI_CHAR, dest, myrank, icomm);
|
||||||
|
assert(0==ierr);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
16
sheet7/E1234/greetings.h
Normal file
16
sheet7/E1234/greetings.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// general header for all functions in directory
|
||||||
|
|
||||||
|
#ifndef GREETINGS_FILE
|
||||||
|
#define GREETINGS_FILE
|
||||||
|
|
||||||
|
#include <mpi.h>
|
||||||
|
|
||||||
|
/** Each process finds out its host, sends this information
|
||||||
|
to root process 0 which prints this information for each process.
|
||||||
|
@param[in] icomm the MPI process group that is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void greetings(MPI_Comm const &icomm);
|
||||||
|
void greetings_cpp(MPI_Comm const &icomm);
|
||||||
|
|
||||||
|
#endif
|
||||||
33
sheet7/E1234/main.cpp
Normal file
33
sheet7/E1234/main.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// MPI code in C++.
|
||||||
|
// See [Gropp/Lusk/Skjellum, "Using MPI", p.33/41 etc.]
|
||||||
|
// and /opt/mpich/include/mpi2c++/comm.h for details
|
||||||
|
|
||||||
|
#include "greetings.h"
|
||||||
|
#include <iostream> // MPI
|
||||||
|
#include <mpi.h>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
MPI_Comm icomm = MPI_COMM_WORLD;
|
||||||
|
MPI_Init(&argc, &argv);
|
||||||
|
int myrank, numprocs;
|
||||||
|
//numprocs = 1; // delete this line when uncommenting the next line
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
|
||||||
|
if (0==myrank) {
|
||||||
|
cout << "\n There are " << numprocs << " processes running.\n \n";
|
||||||
|
}
|
||||||
|
|
||||||
|
greetings(icomm);
|
||||||
|
greetings_cpp(icomm);
|
||||||
|
|
||||||
|
if (0==myrank) cout << endl;
|
||||||
|
|
||||||
|
MPI_Finalize();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
17
sheet7/E5678/.vscode/c_cpp_properties.json
vendored
Normal file
17
sheet7/E5678/.vscode/c_cpp_properties.json
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/usr/lib/x86_64-linux-gnu/openmpi/include"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
23
sheet7/E5678/Makefile
Normal file
23
sheet7/E5678/Makefile
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#
|
||||||
|
# Compile with
|
||||||
|
# make 2>&1 | grep -v openmpi
|
||||||
|
# to avoid warnings caused by OpenMPI
|
||||||
|
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
MAIN = main
|
||||||
|
SOURCES = ${MAIN}.cpp
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = ${MAIN}.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
LINKFLAGS +=
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
136
sheet7/E5678/main.cpp
Normal file
136
sheet7/E5678/main.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
|
||||||
|
#include <iostream> // MPI
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
void DebugVector(vector<double> const& xin, MPI_Comm const& icomm)
|
||||||
|
{
|
||||||
|
int myrank, numprocs;
|
||||||
|
|
||||||
|
MPI_Comm_rank(icomm, &myrank);
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
int selectedProcess = 0;
|
||||||
|
while(selectedProcess >= 0 && selectedProcess < numprocs)
|
||||||
|
{
|
||||||
|
if(myrank == 0)
|
||||||
|
{
|
||||||
|
cout << "Enter process number: " << endl;
|
||||||
|
cin >> selectedProcess;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Bcast(&selectedProcess, 1, MPI_INT, 0, icomm);
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
if(myrank == selectedProcess )
|
||||||
|
{
|
||||||
|
for(double x : xin)
|
||||||
|
{
|
||||||
|
cout << x << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double par_scalar(const vector<double>& x, const vector<double>& y, MPI_Comm icomm) {
|
||||||
|
|
||||||
|
double local = 0.0;
|
||||||
|
for (unsigned int i = 0; i < x.size(); ++i) {
|
||||||
|
local += x[i] * y[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
double sum = 0.0;
|
||||||
|
MPI_Allreduce(&local, &sum, 1, MPI_DOUBLE, MPI_SUM, icomm);
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void E7(const vector<double>& x, MPI_Comm comm,
|
||||||
|
double& min, double& max)
|
||||||
|
{
|
||||||
|
double local_min = x[0];
|
||||||
|
double local_max = x[0];
|
||||||
|
|
||||||
|
for (double x_i : x) {
|
||||||
|
if (x_i < local_min)
|
||||||
|
{
|
||||||
|
local_min = x_i;
|
||||||
|
}
|
||||||
|
if (x_i> local_max)
|
||||||
|
{
|
||||||
|
local_max = x_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Allreduce(&local_min, &min, 1, MPI_DOUBLE, MPI_MIN, comm);
|
||||||
|
MPI_Allreduce(&local_max, &max, 1, MPI_DOUBLE, MPI_MAX, comm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
MPI_Comm icomm = MPI_COMM_WORLD;
|
||||||
|
MPI_Init(&argc, &argv);
|
||||||
|
int myrank, numprocs;
|
||||||
|
//numprocs = 1; // delete this line when uncommenting the next line
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
|
||||||
|
if (0==myrank) {
|
||||||
|
cout << "\n There are " << numprocs << " processes running.\n \n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (0==myrank) cout << endl;
|
||||||
|
|
||||||
|
unsigned int n=20;
|
||||||
|
vector<double> x(n);
|
||||||
|
vector<double> y(n);
|
||||||
|
double x_i;
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<n; i++)
|
||||||
|
{
|
||||||
|
x_i = myrank*100+(i%5)*10+i;
|
||||||
|
x[i] = x_i;
|
||||||
|
|
||||||
|
if(myrank == 0 && i == 0)
|
||||||
|
{
|
||||||
|
y[i] = 0.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
y[i] = 1.0/x_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugVector(x,icomm);
|
||||||
|
|
||||||
|
double result = par_scalar(x,y,icomm);
|
||||||
|
|
||||||
|
if(myrank == 0)
|
||||||
|
{
|
||||||
|
cout << "result scalar: " << result << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
double min, max;
|
||||||
|
E7(x,icomm,min,max);
|
||||||
|
if(myrank == 0)
|
||||||
|
{
|
||||||
|
cout << "min: " << min << ", max: "<< max << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MPI_Alltoall(MPI_IN_PLACE, 0, MPI_DOUBLE, x.data(), 5, MPI_DOUBLE, icomm);
|
||||||
|
DebugVector(x,icomm);
|
||||||
|
|
||||||
|
MPI_Finalize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
2877
sheet7/E910111213/Doxyfile
Normal file
2877
sheet7/E910111213/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
54
sheet7/E910111213/Makefile
Normal file
54
sheet7/E910111213/Makefile
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# COMPILER=GCC_SEQ_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
MAIN = main
|
||||||
|
SOURCES = ${MAIN}.cpp vdop.cpp geom.cpp par_geom.cpp
|
||||||
|
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = ${MAIN}.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
# -DNDEBUG
|
||||||
|
# -pg slows down the code on my laptop when using CLANG_
|
||||||
|
LINKFLAGS += -g
|
||||||
|
#-pg
|
||||||
|
#CXXFLAGS += -Q --help=optimizers
|
||||||
|
#CXXFLAGS += -fopt-info
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# additional specific cleaning in this directory
|
||||||
|
clean_all::
|
||||||
|
@rm -f uv.txt
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# special testing
|
||||||
|
# NPROCS = 4
|
||||||
|
#
|
||||||
|
TFILE = t.dat
|
||||||
|
# TTMP = t.tmp
|
||||||
|
#
|
||||||
|
graph: $(PROGRAM)
|
||||||
|
# @rm -f $(TFILE).*
|
||||||
|
# next two lines only sequentially
|
||||||
|
./$(PROGRAM)
|
||||||
|
@mv $(TFILE).000 $(TFILE)
|
||||||
|
# $(MPIRUN) $(MPIFLAGS) -np $(NPROCS) $(PROGRAM)
|
||||||
|
# @echo " "; echo "Manipulate data for graphics."; echo " "
|
||||||
|
# @cat $(TFILE).* > $(TTMP)
|
||||||
|
# @sort -b -k 2 $(TTMP) -o $(TTMP).1
|
||||||
|
# @sort -b -k 1 $(TTMP).1 -o $(TTMP).2
|
||||||
|
# @awk -f nl.awk $(TTMP).2 > $(TFILE)
|
||||||
|
# @rm -f $(TTMP).* $(TTMP) $(TFILE).*
|
||||||
|
#
|
||||||
|
-gnuplot jac.dem
|
||||||
43
sheet7/E910111213/ascii_read_meshvector.m
Normal file
43
sheet7/E910111213/ascii_read_meshvector.m
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
function [ xc, ia, v ] = ascii_read_meshvector( fname )
|
||||||
|
%
|
||||||
|
% Loads the 2D triangular mesh (coordinates, vertex connectivity)
|
||||||
|
% together with values on its vertices from an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The input file format is compatible
|
||||||
|
% with Mesh_2d_3_matlab:Write_ascii_matlab(..) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% IN: fname - filename
|
||||||
|
% OUT: xc - coordinates
|
||||||
|
% ia - mesh connectivity
|
||||||
|
% v - solution vector
|
||||||
|
|
||||||
|
DELIMETER = ' ';
|
||||||
|
|
||||||
|
fprintf('Read file %s\n',fname)
|
||||||
|
|
||||||
|
% Read mesh constants
|
||||||
|
nn = dlmread(fname,DELIMETER,[0 0 0 3]); %% row_1, col_1, row_2, col_2 in C indexing!!!
|
||||||
|
nnode = nn(1);
|
||||||
|
ndim = nn(2);
|
||||||
|
nelem = nn(3);
|
||||||
|
nvert = nn(4);
|
||||||
|
|
||||||
|
% Read coordinates
|
||||||
|
row_start = 0+1;
|
||||||
|
row_end = 0+nnode;
|
||||||
|
xc = dlmread(fname,DELIMETER,[row_start 0 row_end ndim-1]);
|
||||||
|
|
||||||
|
% Read connectivity
|
||||||
|
row_start = row_end+1;
|
||||||
|
row_end = row_end+nelem;
|
||||||
|
ia = dlmread(fname,DELIMETER,[row_start 0 row_end nvert-1]);
|
||||||
|
|
||||||
|
% Read solution
|
||||||
|
row_start = row_end+1;
|
||||||
|
row_end = row_end+nnode;
|
||||||
|
v = dlmread(fname,DELIMETER,[row_start 0 row_end 0]);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
49
sheet7/E910111213/ascii_write_mesh.m
Normal file
49
sheet7/E910111213/ascii_write_mesh.m
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
function ascii_write_mesh( xc, ia, e, basename)
|
||||||
|
%
|
||||||
|
% Saves the 2D triangular mesh in the minimal way (only coordinates, vertex connectivity, minimal boundary edge info)
|
||||||
|
% in an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The output file format is compatible with Mesh_2d_3_matlab:Mesh_2d_3_matlab(std::string const &fname) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
% IN:
|
||||||
|
% coordinates xc: [2][nnode]
|
||||||
|
% connectivity ia: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
% basename: file name without extension
|
||||||
|
%
|
||||||
|
% Data have been generated via <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>.
|
||||||
|
%
|
||||||
|
fname = [basename, '.txt'];
|
||||||
|
|
||||||
|
nnode = int32(size(xc,2));
|
||||||
|
ndim = int32(size(xc,1));
|
||||||
|
nelem = int32(size(ia,2));
|
||||||
|
nvert_e = int32(3);
|
||||||
|
|
||||||
|
|
||||||
|
dlmwrite(fname,nnode,'delimiter','\t','precision',16) % number of nodes
|
||||||
|
dlmwrite(fname,ndim,'-append','delimiter','\t','precision',16) % space dimension
|
||||||
|
dlmwrite(fname,nelem,'-append','delimiter','\t','precision',16) % number of elements
|
||||||
|
dlmwrite(fname,nvert_e,'-append','delimiter','\t','precision',16) % number of vertices per element
|
||||||
|
|
||||||
|
% dlmwrite(fname,xc(:),'-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
dlmwrite(fname,xc([1,2],:).','-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
|
||||||
|
% no subdomain info transferred
|
||||||
|
tmp=int32(ia(1:3,:));
|
||||||
|
% dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
|
||||||
|
% store only start and end point of boundary edges,
|
||||||
|
nbedges = size(e,2);
|
||||||
|
dlmwrite(fname,nbedges,'-append','delimiter','\t','precision',16) % number boundary edges
|
||||||
|
tmp=int32(e(1:2,:));
|
||||||
|
% dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
|
||||||
|
end
|
||||||
51
sheet7/E910111213/ascii_write_subdomains.m
Normal file
51
sheet7/E910111213/ascii_write_subdomains.m
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
function ascii_write_subdomains( xc, ia, e, basename)
|
||||||
|
%
|
||||||
|
% Saves the 2D triangular mesh in the minimal way (only coordinates, vertex connectivity, minimal boundary edge info)
|
||||||
|
% in an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The output file format is compatible with Mesh_2d_3_matlab:Mesh_2d_3_matlab(std::string const &fname) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
% IN:
|
||||||
|
% coordinates xc: [2][nnode]
|
||||||
|
% connectivity ia: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
% basename: file name without extension
|
||||||
|
%
|
||||||
|
% Data have been generated via <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>.
|
||||||
|
%
|
||||||
|
fname = [basename, '_sd.txt'];
|
||||||
|
|
||||||
|
nnode = int32(size(xc,2));
|
||||||
|
ndim = int32(size(xc,1));
|
||||||
|
nelem = int32(size(ia,2));
|
||||||
|
nvert_e = int32(3);
|
||||||
|
|
||||||
|
|
||||||
|
% dlmwrite(fname,nnode,'delimiter','\t','precision',16) % number of nodes
|
||||||
|
% dlmwrite(fname,ndim,'-append','delimiter','\t','precision',16) % space dimension
|
||||||
|
% dlmwrite(fname,nelem,'-append','delimiter','\t','precision',16) % number of elements
|
||||||
|
dlmwrite(fname,nelem,'delimiter','\t','precision',16) % number of elements
|
||||||
|
% dlmwrite(fname,nvert_e,'-append','delimiter','\t','precision',16) % number of vertices per element
|
||||||
|
|
||||||
|
% % dlmwrite(fname,xc(:),'-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
% dlmwrite(fname,xc([1,2],:).','-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
|
||||||
|
% subdomain info
|
||||||
|
tmp=int32(ia(4,:));
|
||||||
|
% % dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
% dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t') % connectivity in Matlab indexing
|
||||||
|
|
||||||
|
% % store only start and end point of boundary edges,
|
||||||
|
% nbedges = size(e,2);
|
||||||
|
% dlmwrite(fname,nbedges,'-append','delimiter','\t','precision',16) % number boundary edges
|
||||||
|
% tmp=int32(e(1:2,:));
|
||||||
|
% % dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
% dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
|
||||||
|
end
|
||||||
1278
sheet7/E910111213/geom.cpp
Normal file
1278
sheet7/E910111213/geom.cpp
Normal file
File diff suppressed because it is too large
Load diff
712
sheet7/E910111213/geom.h
Normal file
712
sheet7/E910111213/geom.h
Normal file
|
|
@ -0,0 +1,712 @@
|
||||||
|
#ifndef GEOM_FILE
|
||||||
|
#define GEOM_FILE
|
||||||
|
#include <array>
|
||||||
|
#include <functional> // function; C++11
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory> // shared_ptr
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basis class for finite element meshes.
|
||||||
|
*/
|
||||||
|
class Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor initializing the members with default values.
|
||||||
|
*
|
||||||
|
* @param[in] ndim space dimensions (dimension for coordinates)
|
||||||
|
* @param[in] nvert_e number of vertices per element (dimension for connectivity)
|
||||||
|
* @param[in] ndof_e degrees of freedom per element (= @p nvert_e for linear elements)
|
||||||
|
* @param[in] nedge_e number of edges per element (= @p nvert_e for linear elements in 2D)
|
||||||
|
*/
|
||||||
|
explicit Mesh(int ndim, int nvert_e = 0, int ndof_e = 0, int nedge_e = 0);
|
||||||
|
|
||||||
|
__attribute__((noinline))
|
||||||
|
Mesh(Mesh const &) = default;
|
||||||
|
|
||||||
|
Mesh &operator=(Mesh const &) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*
|
||||||
|
* See clang warning on
|
||||||
|
* <a href="https://stackoverflow.com/questions/28786473/clang-no-out-of-line-virtual-method-definitions-pure-abstract-c-class/40550578">weak-vtables</a>.
|
||||||
|
*/
|
||||||
|
virtual ~Mesh();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* File format, see ascii_write_mesh.m
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
*/
|
||||||
|
explicit Mesh(std::string const &fname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* File format, see ascii_write_mesh.m
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
*/
|
||||||
|
void ReadVertexBasedMesh(std::string const &fname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of finite elements in (sub)domain.
|
||||||
|
* @return number of elements.
|
||||||
|
*/
|
||||||
|
int Nelems() const
|
||||||
|
{
|
||||||
|
return _nelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of vertices for each finite element.
|
||||||
|
* @return number of vertices per element.
|
||||||
|
*/
|
||||||
|
int NverticesElements() const
|
||||||
|
{
|
||||||
|
return _nvert_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of degrees of freedom (dof) for each finite element.
|
||||||
|
* @return degrees of freedom per element.
|
||||||
|
*/
|
||||||
|
int NdofsElement() const
|
||||||
|
{
|
||||||
|
return _ndof_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of vertices in mesh.
|
||||||
|
* @return number of vertices.
|
||||||
|
*/
|
||||||
|
int Nnodes() const
|
||||||
|
{
|
||||||
|
return _nnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Space dimension.
|
||||||
|
* @return number of dimensions.
|
||||||
|
*/
|
||||||
|
int Ndims() const
|
||||||
|
{
|
||||||
|
return _ndim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re-)Allocates memory for the element connectivity and redefines the appropriate dimensions.
|
||||||
|
*
|
||||||
|
* @param[in] nelem number of elements
|
||||||
|
* @param[in] nvert_e number of vertices per element
|
||||||
|
*/
|
||||||
|
void Resize_Connectivity(int nelem, int nvert_e)
|
||||||
|
{
|
||||||
|
SetNelem(nelem); // number of elements
|
||||||
|
SetNverticesElement(nvert_e); // vertices per element
|
||||||
|
_ia.resize(nelem * nvert_e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read connectivity information (g1,g2,g3)_i.
|
||||||
|
* @return connectivity vector [nelems*ndofs].
|
||||||
|
*/
|
||||||
|
const std::vector<int> &GetConnectivity() const
|
||||||
|
{
|
||||||
|
return _ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change connectivity information (g1,g2,g3)_i.
|
||||||
|
* @return connectivity vector [nelems*ndofs].
|
||||||
|
*/
|
||||||
|
std::vector<int> &GetConnectivity()
|
||||||
|
{
|
||||||
|
return _ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re-)Allocates memory for the element connectivity and redefines the appropriate dimensions.
|
||||||
|
*
|
||||||
|
* @param[in] nnodes number of nodes
|
||||||
|
* @param[in] ndim space dimension
|
||||||
|
*/
|
||||||
|
void Resize_Coords(int nnodes, int ndim)
|
||||||
|
{
|
||||||
|
SetNnode(nnodes); // number of nodes
|
||||||
|
SetNdim(ndim); // space dimension
|
||||||
|
_xc.resize(nnodes * ndim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read coordinates of vertices (x,y)_i.
|
||||||
|
* @return coordinates vector [nnodes*2].
|
||||||
|
*/
|
||||||
|
const std::vector<double> &GetCoords() const
|
||||||
|
{
|
||||||
|
return _xc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change coordinates of vertices (x,y)_i.
|
||||||
|
* @return coordinates vector [nnodes*2].
|
||||||
|
*/
|
||||||
|
std::vector<double> &GetCoords()
|
||||||
|
{
|
||||||
|
return _xc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate values in vector @p v via function @p func(x,y)
|
||||||
|
* @param[in] v vector
|
||||||
|
* @param[in] func function of (x,y) returning a double value.
|
||||||
|
*/
|
||||||
|
void SetValues(std::vector<double> &v, const std::function<double(double, double)> &func) const;
|
||||||
|
void SetBoundaryValues(std::vector<double> &v, const std::function<double(double, double)> &func) const;
|
||||||
|
void SetDirchletValues(std::vector<double> &v, const std::function<double(double, double)> &func) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the information for a finite element mesh
|
||||||
|
*/
|
||||||
|
void Debug() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the edge based information for a finite element mesh
|
||||||
|
*/
|
||||||
|
void DebugEdgeBased() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
virtual std::vector<int> Index_DirichletNodes() const;
|
||||||
|
virtual std::vector<int> Index_BoundaryNodes() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write vector @p v together with its mesh information to an ASCii file @p fname.
|
||||||
|
*
|
||||||
|
* The data are written in C-style.
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
* @param[in] v vector
|
||||||
|
*/
|
||||||
|
void Write_ascii_matlab(std::string const &fname, std::vector<double> const &v) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports the mesh information to ASCii files @p basename + {_coords|_elements}.txt.
|
||||||
|
*
|
||||||
|
* The data are written in C-style.
|
||||||
|
*
|
||||||
|
* @param[in] basename first part of file names
|
||||||
|
*/
|
||||||
|
void Export_scicomp(std::string const &basename) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualize @p v together with its mesh information via matlab or octave.
|
||||||
|
*
|
||||||
|
* Comment/uncomment those code lines in method Mesh:Visualize (geom.cpp)
|
||||||
|
* that are supported on your system.
|
||||||
|
*
|
||||||
|
* @param[in] v vector
|
||||||
|
*
|
||||||
|
* @warning matlab files ascii_read_meshvector.m visualize_results.m
|
||||||
|
* must be in the executing directory.
|
||||||
|
*/
|
||||||
|
void Visualize(std::vector<double> const &v) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of edges.
|
||||||
|
* @return number of edges in mesh.
|
||||||
|
*/
|
||||||
|
int Nedges() const
|
||||||
|
{
|
||||||
|
return _nedge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of edges for each finite element.
|
||||||
|
* @return number of edges per element.
|
||||||
|
*/
|
||||||
|
int NedgesElements() const
|
||||||
|
{
|
||||||
|
return _nedge_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read edge connectivity information (e1,e2,e3)_i.
|
||||||
|
* @return edge connectivity vector [nelems*_nedge_e].
|
||||||
|
*/
|
||||||
|
const std::vector<int> &GetEdgeConnectivity() const
|
||||||
|
{
|
||||||
|
return _ea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change edge connectivity information (e1,e2,e3)_i.
|
||||||
|
* @return edge connectivity vector [nelems*_nedge_e].
|
||||||
|
*/
|
||||||
|
std::vector<int> &GetEdgeConnectivity()
|
||||||
|
{
|
||||||
|
return _ea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read edge information (v1,v2)_i.
|
||||||
|
* @return edge connectivity vector [_nedge*2].
|
||||||
|
*/
|
||||||
|
const std::vector<int> &GetEdges() const
|
||||||
|
{
|
||||||
|
return _edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change edge information (v1,v2)_i.
|
||||||
|
* @return edge connectivity vector [_nedge*2].
|
||||||
|
*/
|
||||||
|
std::vector<int> &GetEdges()
|
||||||
|
{
|
||||||
|
return _edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines all node to node connections from the vertex based mesh.
|
||||||
|
*
|
||||||
|
* @return vector[k][] containing all connections of vertex k, including to itself.
|
||||||
|
*/
|
||||||
|
std::vector<std::vector<int>> Node2NodeGraph() const
|
||||||
|
{
|
||||||
|
//// Check version 2 wrt. version 1
|
||||||
|
//auto v1=Node2NodeGraph_1();
|
||||||
|
//auto v2=Node2NodeGraph_2();
|
||||||
|
//if ( equal(v1.cbegin(),v1.cend(),v2.begin()) )
|
||||||
|
//{
|
||||||
|
//std::cout << "\nidentical Versions\n";
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
//std::cout << "\nE R R O R in Versions\n";
|
||||||
|
//}
|
||||||
|
|
||||||
|
//return Node2NodeGraph_1();
|
||||||
|
return Node2NodeGraph_2(); // 2 times faster than version 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the father-of-nodes relation.
|
||||||
|
*
|
||||||
|
* @return vector of length 0 because no relation available.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
virtual std::vector<int> const &GetFathersOfVertices() const
|
||||||
|
{
|
||||||
|
return _dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all edge connectivity information (saves memory).
|
||||||
|
*/
|
||||||
|
void Del_EdgeConnectivity();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//public:
|
||||||
|
void SetNelem(int nelem)
|
||||||
|
{
|
||||||
|
_nelem = nelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNverticesElement(int nvert)
|
||||||
|
{
|
||||||
|
_nvert_e = nvert;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNdofsElement(int ndof)
|
||||||
|
{
|
||||||
|
_ndof_e = ndof;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNnode(int nnode)
|
||||||
|
{
|
||||||
|
_nnode = nnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNdim(int ndim)
|
||||||
|
{
|
||||||
|
_ndim = ndim;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNedge(int nedge)
|
||||||
|
{
|
||||||
|
_nedge = nedge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads vertex based mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* File format, see ascii_write_mesh.m
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
*/
|
||||||
|
void ReadVectexBasedMesh(std::string const &fname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The vertex based mesh data are used to derive the edge based data.
|
||||||
|
*
|
||||||
|
* @warning Exactly 3 vertices, 3 edges per element are assumed (linear triangle in 2D)
|
||||||
|
*/
|
||||||
|
void DeriveEdgeFromVertexBased()
|
||||||
|
{
|
||||||
|
//DeriveEdgeFromVertexBased_slow();
|
||||||
|
//DeriveEdgeFromVertexBased_fast();
|
||||||
|
DeriveEdgeFromVertexBased_fast_2();
|
||||||
|
}
|
||||||
|
void DeriveEdgeFromVertexBased_slow();
|
||||||
|
void DeriveEdgeFromVertexBased_fast();
|
||||||
|
void DeriveEdgeFromVertexBased_fast_2();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The edge based mesh data are used to derive the vertex based data.
|
||||||
|
*
|
||||||
|
* @warning Exactly 3 vertices, 3 edges per element are assumed (linear triangle in 2D)
|
||||||
|
*/
|
||||||
|
void DeriveVertexFromEdgeBased();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
int Nnbedges() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(_bedges.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the array dimensions fit to their appropriate size parameters
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
virtual bool Check_array_dimensions() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permutes the vertex information in an edge based mesh.
|
||||||
|
*
|
||||||
|
* @param[in] old2new new indices of original vertices.
|
||||||
|
*/
|
||||||
|
void PermuteVertices_EdgeBased(std::vector<int> const &old2new);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Determines all node to node connections from the vertex based mesh.
|
||||||
|
*
|
||||||
|
* @return vector[k][] containing all connections of vertex k, including to itself.
|
||||||
|
*/
|
||||||
|
std::vector<std::vector<int>> Node2NodeGraph_1() const; // is correct
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines all node to node connections from the vertex based mesh.
|
||||||
|
*
|
||||||
|
* Faster than @p Node2NodeGraph_1().
|
||||||
|
*
|
||||||
|
* @return vector[k][] containing all connections of vertex k, including to itself.
|
||||||
|
*/
|
||||||
|
std::vector<std::vector<int>> Node2NodeGraph_2() const; // is correct
|
||||||
|
|
||||||
|
//private:
|
||||||
|
protected:
|
||||||
|
int _nelem; //!< number elements
|
||||||
|
int _nvert_e; //!< number of vertices per element
|
||||||
|
int _ndof_e; //!< degrees of freedom (d.o.f.) per element
|
||||||
|
int _nnode; //!< number nodes/vertices
|
||||||
|
int _ndim; //!< space dimension of the problem (1, 2, or 3)
|
||||||
|
std::vector<int> _ia; //!< element connectivity
|
||||||
|
std::vector<double> _xc; //!< coordinates
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// B.C.
|
||||||
|
std::vector<int> _bedges; //!< boundary edges [nbedges][2] storing start/end vertex
|
||||||
|
// 2020-01-08
|
||||||
|
std::vector<int> _sdedges; //!< boundary edges [nbedges][2] with left/right subdomain number
|
||||||
|
|
||||||
|
//private:
|
||||||
|
protected:
|
||||||
|
// edge based connectivity
|
||||||
|
int _nedge; //!< number of edges in mesh
|
||||||
|
int _nedge_e; //!< number of edges per element
|
||||||
|
std::vector<int> _edges; //!< edges of mesh (vertices ordered ascending)
|
||||||
|
std::vector<int> _ea; //!< edge based element connectivity
|
||||||
|
// B.C.
|
||||||
|
std::vector<int> _ebedges; //!< boundary edges [nbedges]
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<int> _dummy; //!< empty dummy vector
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
class RefinedMesh: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructs a refined mesh according to the marked elements in @p ibref.
|
||||||
|
*
|
||||||
|
* If the vector @p ibref has size 0 then all elements will be refined.
|
||||||
|
*
|
||||||
|
* @param[in] cmesh original mesh for coarsening.
|
||||||
|
* @param[in] ibref vector containing True/False regarding refinement for each element
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//explicit RefinedMesh(Mesh const &cmesh, std::vector<bool> const &ibref = std::vector<bool>(0));
|
||||||
|
RefinedMesh(Mesh const &cmesh, std::vector<bool> const &ibref);
|
||||||
|
//RefinedMesh(Mesh const &cmesh, std::vector<bool> const &ibref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a refined mesh by regulare refinement of all elements.
|
||||||
|
*
|
||||||
|
* @param[in] cmesh original mesh for coarsening.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
explicit RefinedMesh(Mesh const &cmesh)
|
||||||
|
: RefinedMesh(cmesh, std::vector<bool>(0))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
RefinedMesh(RefinedMesh const &) = delete;
|
||||||
|
//RefinedMesh(RefinedMesh const&&) = delete;
|
||||||
|
|
||||||
|
RefinedMesh &operator=(RefinedMesh const &) = delete;
|
||||||
|
//RefinedMesh& operator=(RefinedMesh const&&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~RefinedMesh() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refines the mesh according to the marked elements.
|
||||||
|
*
|
||||||
|
* @param[in] ibref vector containing True/False regarding refinement for each element
|
||||||
|
*
|
||||||
|
* @return the refined mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh RefineElements(std::vector<bool> const &ibref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refines all elements in the actual mesh.
|
||||||
|
*
|
||||||
|
* @param[in] nref number of regular refinements to perform
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void RefineAllElements(int nref = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the father-of-nodes relation.
|
||||||
|
*
|
||||||
|
* @return father-of-nodes relation [nnodes][2]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
std::vector<int> const &GetFathersOfVertices() const override
|
||||||
|
{
|
||||||
|
return _vfathers;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Checks whether the array dimensions fit to their appropriate size parameters
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
bool Check_array_dimensions() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permutes the vertex information in an edge based mesh.
|
||||||
|
*
|
||||||
|
* @param[in] old2new new indices of original vertices.
|
||||||
|
*/
|
||||||
|
void PermuteVertices_EdgeBased(std::vector<int> const &old2new);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//Mesh const & _cmesh; //!< coarse mesh
|
||||||
|
std::vector<bool> const _ibref; //!< refinement info
|
||||||
|
int _nref; //!< number of regular refinements performed
|
||||||
|
std::vector<int> _vfathers; //!< stores the 2 fathers of each vertex (equal fathers denote original coarse vertex)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
class gMesh_Hierarchy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructs mesh hierarchy of @p nlevel levels starting with coarse mesh @p cmesh.
|
||||||
|
* The coarse mesh @p cmesh will be @p nlevel-1 times geometrically refined.
|
||||||
|
*
|
||||||
|
* @param[in] cmesh initial coarse mesh
|
||||||
|
* @param[in] nlevel number levels in mesh hierarchy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
gMesh_Hierarchy(Mesh const &cmesh, int nlevel);
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
return _gmesh.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to mesh @p lev from mesh hierarchy.
|
||||||
|
*
|
||||||
|
* @return mesh @p lev
|
||||||
|
* @warning An out_of_range exception might be thrown.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh const &operator[](int lev) const
|
||||||
|
{
|
||||||
|
return *_gmesh.at(lev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to finest mesh in mesh hierarchy.
|
||||||
|
*
|
||||||
|
* @return finest mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh const &finest() const
|
||||||
|
{
|
||||||
|
return *_gmesh.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to coarest mesh in mesh hierarchy.
|
||||||
|
*
|
||||||
|
* @return coarsest mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh const &coarsest() const
|
||||||
|
{
|
||||||
|
return *_gmesh.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<Mesh>> _gmesh; //!< mesh hierarchy from coarse ([0]) to fine.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
/**
|
||||||
|
* 2D finite element mesh of the square consisting of linear triangular elements.
|
||||||
|
*/
|
||||||
|
class Mesh_2d_3_square: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Generates the f.e. mesh for the unit square.
|
||||||
|
*
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in] myid my MPI-rank / subdomain
|
||||||
|
* @param[in] procx number of ranks/subdomains in x-direction
|
||||||
|
* @param[in] procy number of processes in y-direction
|
||||||
|
*/
|
||||||
|
Mesh_2d_3_square(int nx, int ny, int myid = 0, int procx = 1, int procy = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
~Mesh_2d_3_square() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set solution vector based on a tensor product grid in the rectangle.
|
||||||
|
* @param[in] u solution vector
|
||||||
|
*/
|
||||||
|
void SetU(std::vector<double> &u) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set right hand side (rhs) vector on a tensor product grid in the rectangle.
|
||||||
|
* @param[in] f rhs vector
|
||||||
|
*/
|
||||||
|
void SetF(std::vector<double> &f) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
std::vector<int> Index_DirichletNodes() const override;
|
||||||
|
std::vector<int> Index_BoundaryNodes() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the values of vector @p u of (sub)domain into a file @p name for further processing in gnuplot.
|
||||||
|
* The file stores rowise the x- and y- coordinates together with the value from @p u .
|
||||||
|
* The domain [@p xl, @p xr] x [@p yb, @p yt] is discretized into @p nx x @p ny intervals.
|
||||||
|
*
|
||||||
|
* @param[in] name basename of file name (file name will be extended by the rank number)
|
||||||
|
* @param[in] u local vector
|
||||||
|
*
|
||||||
|
* @warning Assumes tensor product grid in unit square; rowise numbered
|
||||||
|
* (as generated in class constructor).
|
||||||
|
* The output is provided for tensor product grid visualization
|
||||||
|
* ( similar to Matlab-surf() ).
|
||||||
|
*
|
||||||
|
* @see Mesh_2d_3_square
|
||||||
|
*/
|
||||||
|
void SaveVectorP(std::string const &name, std::vector<double> const &u) const;
|
||||||
|
|
||||||
|
// here will still need to implement in the class
|
||||||
|
// GetBound(), AddBound()
|
||||||
|
// or better a generalized way with indices and their appropriate ranks for MPI communication
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Determines the coordinates of the discretization nodes of the domain [@p xl, @p xr] x [@p yb, @p yt]
|
||||||
|
* which is discretized into @p nx x @p ny intervals.
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in] xl x-coordinate of left boundary
|
||||||
|
* @param[in] xr x-coordinate of right boundary
|
||||||
|
* @param[in] yb y-coordinate of lower boundary
|
||||||
|
* @param[in] yt y-coordinate of upper boundary
|
||||||
|
* @param[out] xc coordinate vector of length 2n with x(2*k,2*k+1) as coordinates of node k
|
||||||
|
*/
|
||||||
|
|
||||||
|
void GetCoordsInRectangle(int nx, int ny, double xl, double xr, double yb, double yt,
|
||||||
|
double xc[]);
|
||||||
|
/**
|
||||||
|
* Determines the element connectivity of linear triangular elements of a FEM discretization
|
||||||
|
* of a rectangle using @p nx x @p ny equidistant intervals for discretization.
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[out] ia element connectivity matrix with ia(3*s,3*s+1,3*s+2) as node numbers od element s
|
||||||
|
*/
|
||||||
|
void GetConnectivityInRectangle(int nx, int ny, int ia[]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _myid; //!< my MPI rank
|
||||||
|
int _procx; //!< number of MPI ranks in x-direction
|
||||||
|
int _procy; //!< number of MPI ranks in y-direction
|
||||||
|
std::array<int, 4> _neigh; //!< MPI ranks of neighbors (negative: no neighbor but b.c.)
|
||||||
|
int _color; //!< red/black coloring (checker board) of subdomains
|
||||||
|
|
||||||
|
double _xl; //!< x coordinate of lower left corner of square
|
||||||
|
double _xr; //!< x coordinate of lower right corner of square
|
||||||
|
double _yb; //!< y coordinate or lower left corner of square
|
||||||
|
double _yt; //!< y coordinate of upper right corner of square
|
||||||
|
int _nx; //!< number of intervals in x-direction
|
||||||
|
int _ny; //!< number of intervals in y-direction
|
||||||
|
};
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
108
sheet7/E910111213/main.cpp
Normal file
108
sheet7/E910111213/main.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
// MPI code in C++.
|
||||||
|
// See [Gropp/Lusk/Skjellum, "Using MPI", p.33/41 etc.]
|
||||||
|
// and /opt/mpich/include/mpi2c++/comm.h for details
|
||||||
|
|
||||||
|
#include "geom.h"
|
||||||
|
#include "par_geom.h"
|
||||||
|
#include "vdop.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mpi.h> // MPI
|
||||||
|
#include <omp.h> // OpenMP
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv )
|
||||||
|
{
|
||||||
|
MPI_Init(&argc, &argv);
|
||||||
|
MPI_Comm const icomm(MPI_COMM_WORLD);
|
||||||
|
omp_set_num_threads(1); // don't use OMP parallelization for a start
|
||||||
|
//
|
||||||
|
|
||||||
|
int np;
|
||||||
|
MPI_Comm_size(icomm, &np);
|
||||||
|
|
||||||
|
//assert(4 == np); // example is only provided for 4 MPI processes
|
||||||
|
|
||||||
|
|
||||||
|
if(np == 4 || np ==2 || np == 1)
|
||||||
|
{
|
||||||
|
// #####################################################################
|
||||||
|
// ---- Read the f.e. mesh and the mapping of elements to MPI processes
|
||||||
|
//Mesh const mesh_c("square_4.txt"); // Files square_4.txt and square_4_sd.txt are needed
|
||||||
|
ParMesh const mesh("square",icomm);
|
||||||
|
|
||||||
|
int const numprocs = mesh.NumProcs();
|
||||||
|
int const myrank = mesh.MyRank();
|
||||||
|
if ( 0 == myrank ) {
|
||||||
|
cout << "\n There are " << numprocs << " processes running.\n \n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int const check_rank=0; // choose the MPI process you would like to check the mesh
|
||||||
|
//if ( check_rank == myrank ) mesh.Debug();
|
||||||
|
//if ( check_rank == myrank ) mesh.DebugEdgeBased();
|
||||||
|
|
||||||
|
// ---- allocate local vectors and check skalar product and vector accumulation
|
||||||
|
vector<double> xl(mesh.Nnodes(), -1.0);
|
||||||
|
mesh.SetValues(xl, [](double x, double y) -> double {return x * x * std::sin(2.5 * M_PI * y);} );
|
||||||
|
|
||||||
|
if (check_rank==myrank) mesh.Visualize(xl);
|
||||||
|
|
||||||
|
cout << "nnodes: " <<mesh.Nnodes() << endl;
|
||||||
|
for (size_t k=0; k<xl.size(); ++k)
|
||||||
|
{
|
||||||
|
xl[k] = 1.0;
|
||||||
|
}
|
||||||
|
double ss = mesh.dscapr(xl,xl);
|
||||||
|
cout << myrank << " : scalar : " << ss << endl;
|
||||||
|
|
||||||
|
mesh.VecAccu(xl);
|
||||||
|
|
||||||
|
if (check_rank==myrank) mesh.Visualize(xl);
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------E10
|
||||||
|
vector<int> x2(mesh.Nnodes(), -1);
|
||||||
|
mesh.VecAccu(x2);
|
||||||
|
if(myrank == check_rank)
|
||||||
|
{
|
||||||
|
for(int i: x2)
|
||||||
|
{
|
||||||
|
cout << i << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------E11
|
||||||
|
int global_nodes = mesh.GlobalNnodes();
|
||||||
|
if(myrank == check_rank)
|
||||||
|
{
|
||||||
|
cout << "Global number of nodes = " << global_nodes << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------E12
|
||||||
|
vector<double> x3(mesh.Nnodes(), myrank);
|
||||||
|
|
||||||
|
// check averaging at the interfaces (by visualization)
|
||||||
|
mesh.Average(x3);
|
||||||
|
if (check_rank==myrank) mesh.Visualize(x3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << np << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
MPI_Finalize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
621
sheet7/E910111213/par_geom.cpp
Normal file
621
sheet7/E910111213/par_geom.cpp
Normal file
|
|
@ -0,0 +1,621 @@
|
||||||
|
// see: http://llvm.org/docs/CodingStandards.html#include-style
|
||||||
|
#include "vdop.h"
|
||||||
|
//#include "geom.h"
|
||||||
|
#include "par_geom.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <ctime> // contains clock()
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <numeric> // accumulate()
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
ParMesh::ParMesh(int ndim, int nvert_e, int ndof_e, int nedge_e, MPI_Comm const &icomm)
|
||||||
|
: Mesh(ndim, nvert_e, ndof_e, nedge_e),
|
||||||
|
_icomm(icomm), _numprocs(-1), _myrank(-1),
|
||||||
|
_v_l2g(0), _t_l2g(0), _v_g2l{{}}, _t_g2l{{}}, _valence(0),
|
||||||
|
_sendbuf(0), _sendcounts(0), _sdispls(0),
|
||||||
|
_loc_itf(0), _gloc_itf(0), _buf2loc(0)
|
||||||
|
{
|
||||||
|
MPI_Comm_size(icomm, &_numprocs);
|
||||||
|
MPI_Comm_rank(icomm, &_myrank);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParMesh::~ParMesh()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ParMesh::ParMesh(std::string const &sname, MPI_Comm const &icomm)
|
||||||
|
: ParMesh(2, 3, 3, 3, icomm) // two dimensions, 3 vertices, 3 dofs, 3 edges per element
|
||||||
|
{
|
||||||
|
//const int numprocs = _icomm.Get_size();
|
||||||
|
const string NS = "_" + to_string(_numprocs);
|
||||||
|
const string fname = sname + NS + ".txt";
|
||||||
|
//cout << "############ " << fname << endl;
|
||||||
|
ReadVertexBasedMesh(fname);
|
||||||
|
cout << "\n End of sequential File read \n";
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Until this point a l l processes possess a l l mesh info in g l o b a l numbering
|
||||||
|
//
|
||||||
|
// Now, we have to select the data belonging to my_rank
|
||||||
|
// and we have to create the mapping local to global (l2g) and vice versa (g2l)
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// save the global node mesh (maybe we need it later)
|
||||||
|
DeriveEdgeFromVertexBased(); // and even more
|
||||||
|
Mesh global_mesh(*this); // requires a l o t of memory
|
||||||
|
Del_EdgeConnectivity();
|
||||||
|
|
||||||
|
// read the subdomain info
|
||||||
|
const string dname = sname + NS + "_sd" + ".txt";
|
||||||
|
vector<int> t2d = ReadElementSubdomains(dname); // global mapping triangle to subdomain for all elements
|
||||||
|
|
||||||
|
//const int myrank = _icomm.Get_rank();
|
||||||
|
Transform_Local2Global_Vertex(_myrank, t2d); // Vertex based mesh: now in l o c a l indexing
|
||||||
|
|
||||||
|
DeriveEdgeFromVertexBased(); // Generate also the l o c a l edge based information
|
||||||
|
|
||||||
|
Generate_VectorAdd();
|
||||||
|
|
||||||
|
|
||||||
|
// Now we have to organize the MPI communication of vertices on the subdomain interfaces
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<int> ParMesh::ReadElementSubdomains(string const &dname)
|
||||||
|
{
|
||||||
|
ifstream ifs(dname);
|
||||||
|
if (!(ifs.is_open() && ifs.good())) {
|
||||||
|
cerr << "ParMesh::ReadElementSubdomain: Error cannot open file " << dname << endl;
|
||||||
|
assert(ifs.is_open());
|
||||||
|
}
|
||||||
|
|
||||||
|
int const OFFSET{1}; // Matlab to C indexing
|
||||||
|
cout << "ASCI file " << dname << " opened" << endl;
|
||||||
|
|
||||||
|
// Read some mesh constants
|
||||||
|
int nelem;
|
||||||
|
ifs >> nelem;
|
||||||
|
cout << nelem << " " << Nelems() << endl;
|
||||||
|
assert( Nelems() == nelem);
|
||||||
|
|
||||||
|
// Allocate memory
|
||||||
|
vector<int> t2d(nelem, -1);
|
||||||
|
// Read element mapping
|
||||||
|
for (int k = 0; k < nelem; ++k) {
|
||||||
|
int tmp;
|
||||||
|
ifs >> tmp;
|
||||||
|
//t2d[k] = tmp - OFFSET;
|
||||||
|
// 2020-01-08
|
||||||
|
t2d[k] = min(tmp, NumProcs()) - OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParMesh::Transform_Local2Global_Vertex(int const myrank, vector<int> const &t2d)
|
||||||
|
{
|
||||||
|
// number of local elements
|
||||||
|
const int l_ne = count(t2d.cbegin(), t2d.cend(), myrank);
|
||||||
|
//cout << myrank << ":: " << lne << endl;
|
||||||
|
vector<int> l_ia(l_ne * NverticesElements(), -1); // local elements still with global vertex numbers
|
||||||
|
_t_l2g.resize(l_ne, -1);
|
||||||
|
|
||||||
|
int lk = 0;
|
||||||
|
for (size_t k = 0; k < t2d.size(); ++k) {
|
||||||
|
if (myrank == t2d[k]) {
|
||||||
|
//if (0==myrank)
|
||||||
|
//{
|
||||||
|
//cout << lk << " k " << t2d[k] << endl;
|
||||||
|
//}
|
||||||
|
l_ia[3 * lk ] = _ia[3 * k ];
|
||||||
|
l_ia[3 * lk + 1] = _ia[3 * k + 1];
|
||||||
|
l_ia[3 * lk + 2] = _ia[3 * k + 2]; // local elements still with global vertex numbers
|
||||||
|
_t_l2g[lk] = k; // elements: local to global mapping
|
||||||
|
_t_g2l[k] = lk; // global to local
|
||||||
|
++lk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Checks:
|
||||||
|
assert( count(l_ia.cbegin(), l_ia.cend(), -1) == 0 );
|
||||||
|
assert( count(_t_l2g.cbegin(), _t_l2g.cend(), -1) == 0 );
|
||||||
|
|
||||||
|
// Vertices: local to global mapping
|
||||||
|
auto tmp = l_ia;
|
||||||
|
sort(tmp.begin(), tmp.end());
|
||||||
|
auto ip = unique(tmp.begin(), tmp.end());
|
||||||
|
tmp.erase(ip, tmp.end());
|
||||||
|
_v_l2g = tmp; // Vertices: local to global mapping
|
||||||
|
for (size_t lkv = 0; lkv < _v_l2g.size(); ++lkv) {
|
||||||
|
_v_g2l[_v_l2g[lkv]] = lkv; // global to local
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boundary edges
|
||||||
|
vector<int> l_bedges;
|
||||||
|
vector<int> l_sdedges;
|
||||||
|
for (size_t b = 0; b < _bedges.size(); b += 2) {
|
||||||
|
int const v1 = _bedges[b ]; // global vertex numbers
|
||||||
|
int const v2 = _bedges[b + 1];
|
||||||
|
try {
|
||||||
|
int const lv1 = _v_g2l.at(v1); // map[] would add that element
|
||||||
|
int const lv2 = _v_g2l.at(v2); // but at() throws an exeption
|
||||||
|
l_bedges.push_back(lv1);
|
||||||
|
l_bedges.push_back(lv2); // Boundaries: already in local indexing
|
||||||
|
// 2020-01-08
|
||||||
|
l_sdedges.push_back(_sdedges[b ]);
|
||||||
|
l_sdedges.push_back(_sdedges[b+1]);
|
||||||
|
}
|
||||||
|
catch (std::out_of_range & err) {
|
||||||
|
//cerr << ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// number of local vertices
|
||||||
|
const int l_nn = _v_l2g.size();
|
||||||
|
vector<double> l_xc(Ndims()*l_nn);
|
||||||
|
for (int lkk = 0; lkk < l_nn; ++lkk) {
|
||||||
|
int k = _v_l2g.at(lkk);
|
||||||
|
l_xc[2 * lkk ] = _xc[2 * k ];
|
||||||
|
l_xc[2 * lkk + 1] = _xc[2 * k + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now, we represent the vertex mesh in l o c a l numbering
|
||||||
|
// elements
|
||||||
|
|
||||||
|
for (size_t i = 0; i < l_ia.size(); ++i) {
|
||||||
|
l_ia[i] = _v_g2l.at(l_ia[i]); // element vertices: global to local
|
||||||
|
}
|
||||||
|
SetNelem(l_ne);
|
||||||
|
_ia = l_ia;
|
||||||
|
// boundary
|
||||||
|
_bedges = l_bedges;
|
||||||
|
_sdedges = l_sdedges;
|
||||||
|
// coordinates
|
||||||
|
SetNnode(l_nn);
|
||||||
|
_xc = l_xc;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParMesh::Generate_VectorAdd()
|
||||||
|
{
|
||||||
|
// Some checks
|
||||||
|
int lnn = Nnodes(); // local number of vertices
|
||||||
|
assert(static_cast<int>(_v_l2g.size()) == lnn);
|
||||||
|
int ierr{-12345};
|
||||||
|
|
||||||
|
// ---- Determine global largest vertex index
|
||||||
|
int gidx_max{-1}; // global largest vertex index
|
||||||
|
int lmax = *max_element(_v_l2g.cbegin(), _v_l2g.cend());
|
||||||
|
MPI_Allreduce(&lmax, &gidx_max, 1, MPI_INT, MPI_MAX, _icomm);
|
||||||
|
int gidx_min{-1}; // global smallest vertex index
|
||||||
|
int lmin = *min_element(_v_l2g.cbegin(), _v_l2g.cend());
|
||||||
|
MPI_Allreduce(&lmin, &gidx_min, 1, MPI_INT, MPI_MIN, _icomm);
|
||||||
|
//cout << gidx_min << " " << gidx_max << endl;
|
||||||
|
assert(0 == gidx_min); // global indices have to start with 0
|
||||||
|
|
||||||
|
|
||||||
|
// ---- Determine for all global vertices the number of subdomains it belongs to
|
||||||
|
vector<int> global(gidx_max+1, 0); // global scalar array for vertices
|
||||||
|
for (auto const gidx : _v_l2g) global[gidx] = 1;
|
||||||
|
// https://www.mpi-forum.org/docs/mpi-2.2/mpi22-report/node109.htm
|
||||||
|
ierr = MPI_Allreduce(MPI_IN_PLACE, global.data(), global.size(), MPI_INT, MPI_SUM, _icomm);
|
||||||
|
//if (0 == MyRank()) cout << global << endl;
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//cout << _xc[2*_v_g2l.at(2)] << " , " << _xc[2*_v_g2l.at(2)+1] << endl;
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
|
||||||
|
// now, global[] contains the number of subdomains a global vertex belongs to
|
||||||
|
if ( count(global.cbegin(), global.cend(), 0) > 0 )
|
||||||
|
cerr << "\n !!! Non-continuous global vertex indexing !!!\n";
|
||||||
|
|
||||||
|
// ---- Determine local interface vertices ( <==> global[] > 1 )
|
||||||
|
// _loc_itf, neigh_itf
|
||||||
|
//vector<int> loc_itf; // local indices of interface vertices on this MPI process
|
||||||
|
for (size_t lk = 0; lk < _v_l2g.size(); ++lk) {
|
||||||
|
int const gk = _v_l2g[lk]; // global index of local vertex lk
|
||||||
|
if ( global[gk] > 1 ) {
|
||||||
|
_loc_itf.push_back(lk); // local indices of interface vertices on this MPI process
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//if (0 == MyRank()) cout << "\n..._loc_itf...\n" << _loc_itf << "\n......\n";
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
// ---- global indices of local interface vertices
|
||||||
|
//auto gloc_itf(_loc_itf);
|
||||||
|
_gloc_itf=_loc_itf;
|
||||||
|
for_each(_gloc_itf.begin(), _gloc_itf.end(), [this] (auto & v) -> void { v = _v_l2g[v];} );
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//if (0 == MyRank()) cout << "\n..._gloc_itf...\n" << _gloc_itf << "\n......\n";
|
||||||
|
//DebugVector(_gloc_itf,"_gloc_itf");
|
||||||
|
|
||||||
|
// ---- Determine the global length of interfaces
|
||||||
|
vector<int> vnn(NumProcs(), -1); // number of interface vertices per MPI rank
|
||||||
|
int l_itf(_loc_itf.size()); // # local interface vertices
|
||||||
|
ierr = MPI_Allgather(&l_itf, 1, MPI_INT, vnn.data(), 1, MPI_INT, _icomm);
|
||||||
|
assert(0 == ierr);
|
||||||
|
//cout << vnn << endl;
|
||||||
|
|
||||||
|
// ---- Now we consider only the inferface vertices
|
||||||
|
int snn = accumulate(vnn.cbegin(), vnn.cend(), 0); // required length of array for global interface indices
|
||||||
|
//cout << snn << " " << gnn << endl;
|
||||||
|
vector<int> dispnn(NumProcs(), 0) ; // displacement of interface vertices per MPI rank
|
||||||
|
partial_sum(vnn.cbegin(), vnn.cend() - 1, dispnn.begin() + 1);
|
||||||
|
//cout << dispnn << endl;
|
||||||
|
|
||||||
|
// ---- Get the global indices for all global interfaces
|
||||||
|
vector<int> g_itf(snn, -1); // collects all global indices of the global interfaces
|
||||||
|
// https://www.mpich.org/static//docs/v3.0.x/www3/MPI_Gatherv.html
|
||||||
|
ierr = MPI_Gatherv( _gloc_itf.data(), _gloc_itf.size(), MPI_INT,
|
||||||
|
g_itf.data(), vnn.data(), dispnn.data(), MPI_INT, 0, _icomm);
|
||||||
|
assert(0 == ierr);
|
||||||
|
// https://www.mpich.org/static/docs/v3.1/www3/MPI_Bcast.html
|
||||||
|
ierr = MPI_Bcast(g_itf.data(), g_itf.size(), MPI_INT, 0, _icomm);
|
||||||
|
assert(0 == ierr); // Now, each MPI rank has the all global indices of the global interfaces
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//if (MyRank() == 0) cout << "\n...g_itf...\n" << g_itf << "\n......\n";
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
|
||||||
|
// ----- Determine all MPI ranks a local interface vertex belongs to
|
||||||
|
vector<vector<int>> neigh_itf(_loc_itf.size());// subdomains a local interface vertex belongs to
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk) {
|
||||||
|
const int gvert = _gloc_itf[lk]; // global index of local interface node lk
|
||||||
|
for (int rank = 0; rank < NumProcs(); ++rank) {
|
||||||
|
auto const startl = g_itf.cbegin() + dispnn[rank];
|
||||||
|
auto const endl = startl + vnn[rank];
|
||||||
|
if ( find( startl, endl, gvert) != endl) {
|
||||||
|
neigh_itf[lk].push_back(rank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- check the available info in _loc_itf[lk], _gloc_itf[lk], neigh_itf[lk]
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
////if (MyRank()==0) cout << "\n...neigh_itf ...\n" << neigh_itf << endl;
|
||||||
|
//if (MyRank() == 0) {
|
||||||
|
//for (size_t lk = 0; lk < _loc_itf.size(); ++lk ) {
|
||||||
|
//cout << lk << " : local idx " << _loc_itf[lk] << " , global idx " << _gloc_itf[lk];
|
||||||
|
//cout << " with MPI ranks " << neigh_itf[lk] << endl;
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
|
||||||
|
// ---- store the valence (e.g., the number of subdomains it belongs to) of all local vertices
|
||||||
|
_valence.resize(Nnodes(),1);
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk)
|
||||||
|
{
|
||||||
|
_valence[_loc_itf[lk]] = neigh_itf[lk].size();
|
||||||
|
}
|
||||||
|
//DebugVector(_valence,"_valence",_icomm);
|
||||||
|
|
||||||
|
// ---- We ware going to use MPI_Alltoallv for data exchange on interfaces
|
||||||
|
// https://www.mpi-forum.org/docs/mpi-3.1/mpi31-report/node109.htm#Node109
|
||||||
|
// https://www.open-mpi.org/doc/v4.0/man3/MPI_Alltoallv.3.php
|
||||||
|
//int MPI_Alltoallv(const void* sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype, void* recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype, MPI_Comm comm)
|
||||||
|
//
|
||||||
|
// MPI_Alltoallv needs:
|
||||||
|
// vector<double> sendbuf (MPI_IN_PLACE: used also as recvbuf)
|
||||||
|
// vector<int> sendcounts (the same as for recv)
|
||||||
|
// vector<int> sdispls (the same as for recv)
|
||||||
|
//
|
||||||
|
// We need to map the interface vertices onto the sendbuffer:
|
||||||
|
// vector<int> loc_itf local index of interface vertex lk
|
||||||
|
// vector<int> gloc_itf global index of interface vertex lk
|
||||||
|
// vector<int> buf2loc local indices of sendbuffer positions (the same as for recv)
|
||||||
|
|
||||||
|
// ---- Determine sendcounts[] and sdipls[] from neigh_itf[]
|
||||||
|
//vector<int> _sendcounts(NumProcs(), 0);
|
||||||
|
_sendcounts.resize(NumProcs(), 0);
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk ) {
|
||||||
|
auto const &kneigh = neigh_itf[lk];
|
||||||
|
for (size_t ns = 0; ns < kneigh.size(); ++ns) {
|
||||||
|
++_sendcounts[kneigh[ns]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (MyRank() == 0) cout << "\n..._sendcounts ...\n" << _sendcounts << endl;
|
||||||
|
|
||||||
|
//vector<int> _sdispls(NumProcs(), 0);
|
||||||
|
_sdispls.resize(NumProcs(), 0);
|
||||||
|
partial_sum(_sendcounts.cbegin(), _sendcounts.cend() - 1, _sdispls.begin() + 1);
|
||||||
|
//vector<int> _sdispls(NumProcs()+1, 0);
|
||||||
|
//partial_sum(_sendcounts.cbegin(), _sendcounts.cend(), _sdispls.begin() + 1);
|
||||||
|
//if (MyRank() == 0) cout << "\n..._sdispls ...\n" << _sdispls << endl;
|
||||||
|
|
||||||
|
// ---- Determine size of buffer 'nbuffer' and mapping 'buf2loc'
|
||||||
|
int const nbuffer = accumulate(_sendcounts.cbegin(), _sendcounts.cend(), 0);
|
||||||
|
//vector<int> _buf2loc(nbuffer, -1);
|
||||||
|
_buf2loc.resize(nbuffer, -1);
|
||||||
|
int buf_idx = 0; // position in buffer
|
||||||
|
for (int rank = 0; rank < NumProcs(); ++rank) {
|
||||||
|
assert( buf_idx == _sdispls[rank]);
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk ) {
|
||||||
|
auto const &kneigh = neigh_itf[lk];
|
||||||
|
if (find(kneigh.cbegin(),kneigh.cend(),rank)!=kneigh.cend())
|
||||||
|
{
|
||||||
|
_buf2loc[buf_idx] = _loc_itf[lk];
|
||||||
|
++buf_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (MyRank() == 0) cout << "\n...buf2loc ...\n" << buf2loc << endl;
|
||||||
|
//DebugVector(buf2loc,"buf2loc",_icomm);
|
||||||
|
|
||||||
|
// ---- Allocate send/recv buffer
|
||||||
|
//vector<double> _sendbuf(nbuffer,-1.0);
|
||||||
|
_sendbuf.resize(nbuffer,-1.0);
|
||||||
|
_sendbuf_int.resize(nbuffer,-1);
|
||||||
|
|
||||||
|
assert(CheckInterfaceExchange_InPlace());
|
||||||
|
cout << " Check of data exchange (InPlace) successful!\n";
|
||||||
|
assert(CheckInterfaceExchange());
|
||||||
|
cout << " Check of data exchange successful!\n";
|
||||||
|
assert(CheckInterfaceAdd_InPlace());
|
||||||
|
cout << " Check of data add successful!\n";
|
||||||
|
assert(CheckInterfaceAdd());
|
||||||
|
cout << " Check of data add (InPlace) successful!\n";
|
||||||
|
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
VecAccu(x);
|
||||||
|
cout << " VecAccu (InPlace) successful!\n";
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceExchange_InPlace() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
copy(_v_l2g.cbegin(),_v_l2g.cend(),x.begin()); // init x with global vertex indices
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
int ierr = MPI_Alltoallv(MPI_IN_PLACE, _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = -1.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
y[_buf2loc.at(ls)] = _sendbuf[ls];
|
||||||
|
}
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceExchange() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
copy(_v_l2g.cbegin(),_v_l2g.cend(),x.begin()); // init x with global vertex indices
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
vector<double> recvbuf(_sendbuf.size());
|
||||||
|
int ierr = MPI_Alltoallv(_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
recvbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
//DebugVector(recvbuf,"recvbuf",_icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = -1.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<recvbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
y[_buf2loc.at(ls)] = recvbuf[ls];
|
||||||
|
}
|
||||||
|
//cout << "WRONG : " << count(y.cbegin(),y.cend(), -1.0) << endl;
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceAdd_InPlace() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
for (size_t i=0; i<x.size(); ++i)
|
||||||
|
{
|
||||||
|
x[i] = _xc[2*i]+_xc[2*i+1]; // init x with coordinate values
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
int ierr = MPI_Alltoallv(MPI_IN_PLACE, _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = 0.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
y[_buf2loc.at(ls)] += _sendbuf[ls];
|
||||||
|
}
|
||||||
|
MPI_Barrier(_icomm);
|
||||||
|
//DebugVector(x,"x",_icomm);
|
||||||
|
//DebugVector(y,"y",_icomm);
|
||||||
|
for (size_t i= 0; i<y.size(); ++i) y[i]/=_valence[i]; // divide by valence
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceAdd() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
for (size_t i=0; i<x.size(); ++i)
|
||||||
|
{
|
||||||
|
//x[i] = _xc[2*i]+_xc[2*i+1]; // init x with coordinate values
|
||||||
|
x[i] = _v_l2g[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
vector<double> recvbuf(_sendbuf.size());
|
||||||
|
int ierr = MPI_Alltoallv(_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
recvbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
//DebugVector(recvbuf,"recvbuf",_icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = 0.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<recvbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
//if (0==MyRank()) cout << ls << ": " << _buf2loc.at(ls) << " " << y[_buf2loc.at(ls)] << "("<< x[_buf2loc.at(ls)] << ")" << " " << recvbuf[ls] << " (" << _sendbuf[ls] << ")" << endl;
|
||||||
|
y[_buf2loc.at(ls)] += recvbuf[ls];
|
||||||
|
}
|
||||||
|
MPI_Barrier(_icomm);
|
||||||
|
//DebugVector(x,"x",_icomm);
|
||||||
|
//DebugVector(y,"y",_icomm);
|
||||||
|
for (size_t i= 0; i<y.size(); ++i) y[i]/=_valence[i]; // divide by valence
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
void ParMesh::VecAccu(std::vector<double> &w) const
|
||||||
|
{
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = w[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
int ierr = MPI_Alltoallv(MPI_IN_PLACE, _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) w[_loc_itf.at(lk)] = 0.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
w[_buf2loc.at(ls)] += _sendbuf[ls];
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParMesh::VecAccu(std::vector<int> &w) const
|
||||||
|
{
|
||||||
|
for(size_t ls = 0; ls<_sendbuf_int.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf_int[ls] = w[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
int ierr = MPI_Alltoallv(MPI_IN_PLACE, _sendcounts.data(), _sdispls.data(), MPI_INT,
|
||||||
|
_sendbuf_int.data(), _sendcounts.data(), _sdispls.data(), MPI_INT, _icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) w[_loc_itf.at(lk)] = 0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<_sendbuf_int.size(); ++ls)
|
||||||
|
{
|
||||||
|
w[_buf2loc.at(ls)] += _sendbuf_int[ls];
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int ParMesh::GlobalNnodes() const
|
||||||
|
{
|
||||||
|
double localNodes = 0.0;
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < _valence.size(); i++)
|
||||||
|
{
|
||||||
|
localNodes += 1.0/_valence[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
double globalNodes = 0.0;
|
||||||
|
MPI_Allreduce(&localNodes, &globalNodes, 1, MPI_DOUBLE, MPI_SUM, _icomm);
|
||||||
|
|
||||||
|
return static_cast<unsigned int>(std::round(globalNodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParMesh::Average(std::vector<double> &w) const
|
||||||
|
{
|
||||||
|
VecAccu(w);
|
||||||
|
unsigned int index;
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk)
|
||||||
|
{
|
||||||
|
index = _loc_itf.at(lk);
|
||||||
|
w[index] /= _valence[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
153
sheet7/E910111213/par_geom.h
Normal file
153
sheet7/E910111213/par_geom.h
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
#ifndef PAR_GEOM_FILE
|
||||||
|
#define PAR_GEOM_FILE
|
||||||
|
#include "geom.h"
|
||||||
|
#include "vdop.h"
|
||||||
|
#include <array>
|
||||||
|
#include <functional> // function; C++11
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <memory> // shared_ptr
|
||||||
|
#include <mpi.h> // MPI
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ParMesh: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor initializing the members with default values.
|
||||||
|
*
|
||||||
|
* @param[in] ndim space dimensions (dimension for coordinates)
|
||||||
|
* @param[in] nvert_e number of vertices per element (dimension for connectivity)
|
||||||
|
* @param[in] ndof_e degrees of freedom per element (= @p nvert_e for linear elements)
|
||||||
|
* @param[in] nedge_e number of edges per element (= @p nvert_e for linear elements in 2D)
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
*/
|
||||||
|
explicit ParMesh(int ndim, int nvert_e = 0, int ndof_e = 0, int nedge_e = 0, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
ParMesh(ParMesh const &) = default;
|
||||||
|
|
||||||
|
ParMesh &operator=(ParMesh const &) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*
|
||||||
|
* See clang warning on
|
||||||
|
* <a href="https://stackoverflow.com/questions/28786473/clang-no-out-of-line-virtual-method-definitions-pure-abstract-c-class/40550578">weak-vtables</a>.
|
||||||
|
*/
|
||||||
|
virtual ~ParMesh();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* @param[in] sname suffix of file name
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
* @see ascii_write_mesh.m for the file format.
|
||||||
|
*/
|
||||||
|
explicit ParMesh(std::string const &sname, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
void VecAccu(std::vector<double> &w) const;
|
||||||
|
void VecAccu(std::vector<int> &w) const;
|
||||||
|
|
||||||
|
unsigned int GlobalNnodes() const;
|
||||||
|
void Average(std::vector<double> &w) const;
|
||||||
|
|
||||||
|
/** Inner product
|
||||||
|
* @param[in] x vector
|
||||||
|
* @param[in] y vector
|
||||||
|
* @return resulting Euclidian inner product <x,y>
|
||||||
|
*/
|
||||||
|
double dscapr(std::vector<double> const &x, std::vector<double> const &y) const
|
||||||
|
{
|
||||||
|
return par_scalar(x, y, _icomm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Reads the global triangle to subdomain mapping.
|
||||||
|
*
|
||||||
|
* @param[in] dname file name
|
||||||
|
*
|
||||||
|
* @see ascii_write_subdomains.m for the file format
|
||||||
|
*/
|
||||||
|
std::vector<int> ReadElementSubdomains(std::string const &dname);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform
|
||||||
|
*
|
||||||
|
* @param[in] myrank MPI rank of this process
|
||||||
|
* @param[in] t2d global mapping triangle to subdomain for all elements (vertex based)
|
||||||
|
*/
|
||||||
|
void Transform_Local2Global_Vertex(int myrank, std::vector<int> const &t2d);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform
|
||||||
|
*/
|
||||||
|
void Generate_VectorAdd();
|
||||||
|
|
||||||
|
bool CheckInterfaceExchange_InPlace() const;
|
||||||
|
bool CheckInterfaceExchange() const;
|
||||||
|
bool CheckInterfaceAdd_InPlace() const;
|
||||||
|
bool CheckInterfaceAdd() const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** MPI rank of the calling process in communication group.
|
||||||
|
*
|
||||||
|
* @return MPI rank of the calling process
|
||||||
|
*/
|
||||||
|
int MyRank() const
|
||||||
|
{
|
||||||
|
return _myrank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Number of MPI processes in communication group.
|
||||||
|
*
|
||||||
|
* @return Number of MPI processes
|
||||||
|
*/
|
||||||
|
int NumProcs() const
|
||||||
|
{
|
||||||
|
return _numprocs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns recent
|
||||||
|
* @return MPI communicator
|
||||||
|
*/
|
||||||
|
MPI_Comm GetCommunicator() const
|
||||||
|
{
|
||||||
|
return _icomm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Don't use &_icomm ==> Error
|
||||||
|
MPI_Comm const _icomm; //!< MPI communicator for the group of processes
|
||||||
|
int _numprocs; //!< number of MPI processes
|
||||||
|
int _myrank; //!< my MPI rank
|
||||||
|
std::vector<int> _v_l2g; //!< vertices: local to global mapping
|
||||||
|
std::vector<int> _t_l2g; //!< triangles: local to global mapping
|
||||||
|
std::map<int, int> _v_g2l; //!< vertices: global to local mapping
|
||||||
|
std::map<int, int> _t_g2l; //!< triangles: global to local mapping
|
||||||
|
|
||||||
|
//std::vector<int> e_l2g; //!< edges: local to global mapping
|
||||||
|
|
||||||
|
std::vector<int> _valence; //!< valence of local vertices, i.e. number of subdomains they belong to
|
||||||
|
// MPI_Alltoallv needs:
|
||||||
|
mutable std::vector<double> _sendbuf; //!< send buffer a n d receiving buffer (MPI_IN_PLACE)
|
||||||
|
mutable std::vector<int> _sendbuf_int;
|
||||||
|
|
||||||
|
std::vector<int> _sendcounts; //!< number of data to send to each MPI rank (the same as for recv)
|
||||||
|
std::vector<int> _sdispls; //!< offset of data to send to each MPI rank wrt. _senbuffer (the same as for recv)
|
||||||
|
//
|
||||||
|
// We need to map the interface vertices onto the sendbuffer:
|
||||||
|
std::vector<int> _loc_itf; //!< local index of interface vertex lk
|
||||||
|
std::vector<int> _gloc_itf; //!< global index of interface vertex lk
|
||||||
|
std::vector<int> _buf2loc; //!< local indices of sendbuffer positions (the same as for recv)
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
71
sheet7/E910111213/square_1.m
Normal file
71
sheet7/E910111213/square_1.m
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
% Square:
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
% %% L-shape
|
||||||
|
% g=[2 0 2 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 1 0;
|
||||||
|
% 2 2 1 1 0.5 1 0;
|
||||||
|
% 2 1 1 0.5 2 1 0;
|
||||||
|
% 2 1 0 2 2 1 0;
|
||||||
|
% 2 0 0 2 0 1 0]';
|
||||||
|
|
||||||
|
%% square
|
||||||
|
g=[2 0 1 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 0 1 1 0;
|
||||||
|
2 1 0 1 1 1 0;
|
||||||
|
2 0 0 1 0 1 0]';
|
||||||
|
|
||||||
|
% %% 2 squares
|
||||||
|
%g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 2;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0;
|
||||||
|
% 2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 2 0;
|
||||||
|
% 2 2 1 1 1 2 0
|
||||||
|
% ]';
|
||||||
|
|
||||||
|
%% 4 squares
|
||||||
|
%g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 2;
|
||||||
|
% 2 1 0 1 1 1 3;
|
||||||
|
% 2 0 0 1 0 1 0;
|
||||||
|
% 2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 2 0;
|
||||||
|
% 2 2 1 1 1 2 4;
|
||||||
|
% 2 1 1 1 0 2 1;
|
||||||
|
% 2 0 1 1 1 3 1; % 3 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 1 2 3 4;
|
||||||
|
% 2 1 0 2 2 3 0;
|
||||||
|
% 2 0 0 2 1 3 0;
|
||||||
|
% 2 1 2 1 1 4 2; % 4 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 1 2 4 0;
|
||||||
|
% 2 2 1 2 2 4 0
|
||||||
|
% 2 1 1 2 1 4 3
|
||||||
|
% ]';
|
||||||
|
|
||||||
|
[p,e,t] = initmesh(g,'hmax',0.1);
|
||||||
|
pdemesh(p,e,t)
|
||||||
|
|
||||||
|
%% GH
|
||||||
|
% output from <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>
|
||||||
|
%
|
||||||
|
% coordinates p: [2][nnode]
|
||||||
|
% connectivity t: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
|
||||||
|
ascii_write_mesh( p, t, e, mfilename);
|
||||||
|
|
||||||
|
ascii_write_subdomains( p, t, e, mfilename);
|
||||||
|
|
||||||
|
|
||||||
|
% tmp=t(1:3,:)
|
||||||
|
|
||||||
558
sheet7/E910111213/square_1.txt
Normal file
558
sheet7/E910111213/square_1.txt
Normal file
|
|
@ -0,0 +1,558 @@
|
||||||
|
185
|
||||||
|
2
|
||||||
|
328
|
||||||
|
3
|
||||||
|
0 0
|
||||||
|
1 0
|
||||||
|
1 1
|
||||||
|
0 1
|
||||||
|
0.1 0
|
||||||
|
0.2 0
|
||||||
|
0.3 0
|
||||||
|
0.4 0
|
||||||
|
0.5 0
|
||||||
|
0.6 0
|
||||||
|
0.7 0
|
||||||
|
0.8 0
|
||||||
|
0.9 0
|
||||||
|
1 0.1
|
||||||
|
1 0.2
|
||||||
|
1 0.3
|
||||||
|
1 0.4
|
||||||
|
1 0.5
|
||||||
|
1 0.6
|
||||||
|
1 0.7
|
||||||
|
1 0.8
|
||||||
|
1 0.9
|
||||||
|
0.9 1
|
||||||
|
0.8 1
|
||||||
|
0.7 1
|
||||||
|
0.6 1
|
||||||
|
0.5 1
|
||||||
|
0.4 1
|
||||||
|
0.3 1
|
||||||
|
0.2 1
|
||||||
|
0.09999999999999998 1
|
||||||
|
0 0.9
|
||||||
|
0 0.8
|
||||||
|
0 0.7
|
||||||
|
0 0.6
|
||||||
|
0 0.5
|
||||||
|
0 0.4
|
||||||
|
0 0.3
|
||||||
|
0 0.2
|
||||||
|
0 0.09999999999999998
|
||||||
|
0.479527812121941 0.5130906855242849
|
||||||
|
0.04811823180383969 0.0438546166507735
|
||||||
|
0.9563795599175402 0.04804788885032887
|
||||||
|
0.04386052966676572 0.9518771386464404
|
||||||
|
0.9519837650414075 0.9564710564643847
|
||||||
|
0.7547325605803197 0.3556873639095056
|
||||||
|
0.360761237685547 0.2648713558910208
|
||||||
|
0.2679955285799354 0.6367316063076108
|
||||||
|
0.6565311368147725 0.7282810558667158
|
||||||
|
0.08977947929390173 0.1606758305515394
|
||||||
|
0.16074961553105 0.9101421685880838
|
||||||
|
0.9114032959455121 0.8441430342815788
|
||||||
|
0.8412127393896983 0.09032345243962579
|
||||||
|
0.4520016091121353 0.7693672638162853
|
||||||
|
0.5579173186257795 0.2370236678206477
|
||||||
|
0.2298339342907983 0.4531168320939027
|
||||||
|
0.6870727978845249 0.5344182069836515
|
||||||
|
0.8145967747561291 0.6882672637836746
|
||||||
|
0.2590391808211707 0.1580373572085882
|
||||||
|
0.8521442539624974 0.2588869931794255
|
||||||
|
0.1588406321984697 0.740526673693239
|
||||||
|
0.7456209517439575 0.8415774916282844
|
||||||
|
0.7341263127877148 0.09280026881354901
|
||||||
|
0.2671693065747615 0.909496199134008
|
||||||
|
0.09033464668980155 0.2671883646221719
|
||||||
|
0.8457896962288601 0.4896000777650233
|
||||||
|
0.3404825814904102 0.5045570302191981
|
||||||
|
0.4828554674400058 0.3357874026189672
|
||||||
|
0.5328318433844601 0.6502074760223741
|
||||||
|
0.6097225090876653 0.8567940574787075
|
||||||
|
0.3906433840357024 0.1354694263186264
|
||||||
|
0.1378922468965601 0.6086349988482294
|
||||||
|
0.7110817229397154 0.2318431574832541
|
||||||
|
0.3117181579370819 0.7783142400205344
|
||||||
|
0.220949681304264 0.310667563028674
|
||||||
|
0.5425918070322489 0.07560610459253665
|
||||||
|
0.4430039145575841 0.9116370271655028
|
||||||
|
0.08740928339643227 0.4436913622237557
|
||||||
|
0.7188986206847875 0.6636965188667157
|
||||||
|
0.9110251036728165 0.6437697100153658
|
||||||
|
0.9102437695032523 0.7452606401269005
|
||||||
|
0.1758720830768971 0.1044756994214669
|
||||||
|
0.8258438045125337 0.8981667834525472
|
||||||
|
0.1046890874548641 0.8239996484245049
|
||||||
|
0.8991462273231223 0.1744109197267267
|
||||||
|
0.6051175206745411 0.4230204952626953
|
||||||
|
0.3969635264466733 0.6241613575135659
|
||||||
|
0.3715057937073831 0.3880149382253817
|
||||||
|
0.8242474441869813 0.5849955263397347
|
||||||
|
0.8249925781817751 0.3740463471567774
|
||||||
|
0.524857955574242 0.7417226727211995
|
||||||
|
0.4596212700192013 0.2593236862528195
|
||||||
|
0.2616272257729989 0.5362197465141072
|
||||||
|
0.606859389427135 0.5708877499579769
|
||||||
|
0.6628384081676978 0.1354434799258081
|
||||||
|
0.1417735759502206 0.3537206398808048
|
||||||
|
0.3535213476926991 0.857695106111649
|
||||||
|
0.8243721350238892 0.7953207341692213
|
||||||
|
0.1809418706291789 0.2179884723304038
|
||||||
|
0.2184182171811329 0.8187415498053924
|
||||||
|
0.7884319570292208 0.183777415436584
|
||||||
|
0.9200690792392709 0.4495615809861258
|
||||||
|
0.4451391682507762 0.07311678395656888
|
||||||
|
0.5521636044351103 0.9216944906274662
|
||||||
|
0.07645110424394973 0.5525170940538346
|
||||||
|
0.6459882520842987 0.9291570899039412
|
||||||
|
0.06913750986171868 0.645365744095622
|
||||||
|
0.3540126618242007 0.06796940478874185
|
||||||
|
0.3350672820198897 0.1870674574637768
|
||||||
|
0.2681458646222014 0.07565948812083768
|
||||||
|
0.9304278242313601 0.2557924725551748
|
||||||
|
0.1888675945362029 0.6639844453684917
|
||||||
|
0.07615275558574391 0.7316010144871834
|
||||||
|
0.7330914849187046 0.9235761148662579
|
||||||
|
0.6708523871490314 0.8055961987547425
|
||||||
|
0.9254996827062275 0.09229062813530801
|
||||||
|
0.07558485132732408 0.9074193007828303
|
||||||
|
0.9079441512159013 0.9258426671715853
|
||||||
|
0.09255203863622692 0.07554591808558819
|
||||||
|
0.5680278383791504 0.3330895372138523
|
||||||
|
0.6999347455251212 0.4427774934447353
|
||||||
|
0.9169029401490904 0.54449677714876
|
||||||
|
0.7384739303161019 0.7539389212238149
|
||||||
|
0.3890119777777613 0.7104484710322342
|
||||||
|
0.2878025148437066 0.3851241789215418
|
||||||
|
0.629872124120922 0.6544815099998712
|
||||||
|
0.9007264265272032 0.3468323759374454
|
||||||
|
0.411279904374581 0.4567615871148493
|
||||||
|
0.4654915406621035 0.5928705227932682
|
||||||
|
0.5147995837137257 0.8309665940332217
|
||||||
|
0.1657576147654025 0.5169080635939939
|
||||||
|
0.4842020928392167 0.1607795698062726
|
||||||
|
0.7650269169529201 0.5114318451419555
|
||||||
|
0.7727886666860844 0.2740976924940586
|
||||||
|
0.2419510570158952 0.7238088796353837
|
||||||
|
0.2752622996523991 0.2404916166572419
|
||||||
|
0.4695150046459641 0.7063259741370521
|
||||||
|
0.3347920785441169 0.583686902316204
|
||||||
|
0.4092342435672485 0.3276796179871309
|
||||||
|
0.5063047985714836 0.4204246666548196
|
||||||
|
0.2916489655260076 0.4637829403109103
|
||||||
|
0.5599640954591117 0.4974158353977953
|
||||||
|
0.4058103707982076 0.2011311049665246
|
||||||
|
0.2039249392178127 0.5928750846678578
|
||||||
|
0.5939173661963685 0.7794857474330111
|
||||||
|
0.7083501471507929 0.1677776788423718
|
||||||
|
0.2871826927671263 0.8416108907006823
|
||||||
|
0.6452139711904199 0.198163050302754
|
||||||
|
0.1580509567525808 0.2869843728474166
|
||||||
|
0.06368210143114308 0.3527506715437289
|
||||||
|
0.6379941184879288 0.07475319919242245
|
||||||
|
0.352513946674906 0.9360345024951773
|
||||||
|
0.4295894166119973 0.8326060111402684
|
||||||
|
0.1662397140312891 0.4305970833461407
|
||||||
|
0.7747686535289771 0.6310503316801724
|
||||||
|
0.3210854659795955 0.1245584034703338
|
||||||
|
0.1257665255187338 0.6783828888007957
|
||||||
|
0.6810504641157901 0.8716254757826338
|
||||||
|
0.8566662522803288 0.4178384718512468
|
||||||
|
0.1420330245501709 0.04491064793897617
|
||||||
|
0.9561739529171728 0.141583384682825
|
||||||
|
0.8584457296716212 0.9560409249356761
|
||||||
|
0.04495620004107777 0.8579381142105297
|
||||||
|
0.5171767005108064 0.2908288148650228
|
||||||
|
0.7913019422018426 0.4313726220323573
|
||||||
|
0.6425026537330679 0.274463851858847
|
||||||
|
0.6633492402087484 0.3537206596142247
|
||||||
|
0.6768185989632656 0.6021176410080418
|
||||||
|
0.3093806310187861 0.7008983644164182
|
||||||
|
0.2975174797189623 0.3067216701578878
|
||||||
|
0.6319539373284636 0.4933605852039861
|
||||||
|
0.4046353295336855 0.5461031514210908
|
||||||
|
0.4362702351071284 0.3855427634700271
|
||||||
|
0.7411951440577802 0.5877461636960623
|
||||||
|
0.2088055498119787 0.3863707017530032
|
||||||
|
0.3866467015671689 0.79036800231969
|
||||||
|
0.8211383868684881 0.3213102960013891
|
||||||
|
0.3391487763640905 0.6517998595813517
|
||||||
|
0.4504917745206402 0.6572589474543384
|
||||||
|
0.3403171186033137 0.4396480629283334
|
||||||
|
0.3450512325288959 0.3342143314291603
|
||||||
|
0.5884423212101556 0.1464688161475419
|
||||||
|
0.5874820780580523 0.7111470153304259
|
||||||
|
0.5289939782208927 0.5649267052820812
|
||||||
|
0.7089627135729326 0.297207704024266
|
||||||
|
13 2 43
|
||||||
|
82 6 110
|
||||||
|
7 8 108
|
||||||
|
42 5 119
|
||||||
|
119 5 160
|
||||||
|
6 7 110
|
||||||
|
92 47 143
|
||||||
|
9 10 76
|
||||||
|
76 10 151
|
||||||
|
22 3 45
|
||||||
|
31 4 44
|
||||||
|
85 15 111
|
||||||
|
111 16 127
|
||||||
|
17 18 102
|
||||||
|
102 18 122
|
||||||
|
12 13 53
|
||||||
|
53 13 116
|
||||||
|
43 14 116
|
||||||
|
15 16 111
|
||||||
|
40 1 42
|
||||||
|
134 46 185
|
||||||
|
21 22 52
|
||||||
|
83 24 114
|
||||||
|
25 26 106
|
||||||
|
52 22 118
|
||||||
|
45 23 118
|
||||||
|
24 25 114
|
||||||
|
126 49 183
|
||||||
|
27 28 77
|
||||||
|
77 28 152
|
||||||
|
30 31 51
|
||||||
|
51 31 117
|
||||||
|
44 32 117
|
||||||
|
84 33 113
|
||||||
|
33 34 113
|
||||||
|
34 35 107
|
||||||
|
1 5 42
|
||||||
|
50 40 119
|
||||||
|
93 48 144
|
||||||
|
36 37 78
|
||||||
|
78 37 150
|
||||||
|
39 40 50
|
||||||
|
2 14 43
|
||||||
|
116 14 161
|
||||||
|
4 32 44
|
||||||
|
117 32 163
|
||||||
|
3 23 45
|
||||||
|
118 23 162
|
||||||
|
19 20 80
|
||||||
|
128 41 172
|
||||||
|
166 73 185
|
||||||
|
16 17 127
|
||||||
|
129 41 184
|
||||||
|
8 9 103
|
||||||
|
138 67 172
|
||||||
|
35 36 105
|
||||||
|
40 42 119
|
||||||
|
170 47 181
|
||||||
|
31 44 117
|
||||||
|
169 48 178
|
||||||
|
22 45 118
|
||||||
|
26 27 104
|
||||||
|
13 43 116
|
||||||
|
115 49 123
|
||||||
|
135 48 169
|
||||||
|
29 30 64
|
||||||
|
136 47 170
|
||||||
|
11 12 63
|
||||||
|
79 49 126
|
||||||
|
38 39 65
|
||||||
|
92 55 164
|
||||||
|
94 57 168
|
||||||
|
80 20 81
|
||||||
|
168 57 174
|
||||||
|
109 47 136
|
||||||
|
39 50 65
|
||||||
|
90 46 177
|
||||||
|
12 53 63
|
||||||
|
112 48 135
|
||||||
|
30 51 64
|
||||||
|
20 21 81
|
||||||
|
79 58 123
|
||||||
|
63 53 101
|
||||||
|
139 68 173
|
||||||
|
64 51 100
|
||||||
|
91 54 137
|
||||||
|
65 50 99
|
||||||
|
93 56 141
|
||||||
|
21 52 81
|
||||||
|
121 46 165
|
||||||
|
124 54 176
|
||||||
|
125 56 175
|
||||||
|
148 55 182
|
||||||
|
128 88 173
|
||||||
|
121 57 171
|
||||||
|
93 67 138
|
||||||
|
28 29 152
|
||||||
|
115 62 158
|
||||||
|
10 11 151
|
||||||
|
109 59 156
|
||||||
|
37 38 150
|
||||||
|
112 61 157
|
||||||
|
85 60 101
|
||||||
|
120 55 166
|
||||||
|
84 61 100
|
||||||
|
97 74 176
|
||||||
|
82 59 99
|
||||||
|
96 75 175
|
||||||
|
120 68 164
|
||||||
|
11 63 151
|
||||||
|
129 69 179
|
||||||
|
29 64 152
|
||||||
|
128 67 180
|
||||||
|
38 65 150
|
||||||
|
80 58 89
|
||||||
|
91 69 183
|
||||||
|
81 52 98
|
||||||
|
89 58 155
|
||||||
|
98 62 123
|
||||||
|
58 80 81
|
||||||
|
96 65 149
|
||||||
|
108 71 156
|
||||||
|
83 62 98
|
||||||
|
106 70 158
|
||||||
|
97 64 147
|
||||||
|
107 72 157
|
||||||
|
95 63 146
|
||||||
|
134 60 177
|
||||||
|
159 66 165
|
||||||
|
120 86 140
|
||||||
|
94 69 184
|
||||||
|
124 87 179
|
||||||
|
92 68 139
|
||||||
|
125 88 180
|
||||||
|
58 79 155
|
||||||
|
18 19 122
|
||||||
|
101 60 134
|
||||||
|
89 66 122
|
||||||
|
115 70 145
|
||||||
|
130 91 145
|
||||||
|
99 59 136
|
||||||
|
109 71 143
|
||||||
|
100 61 135
|
||||||
|
112 72 144
|
||||||
|
155 79 174
|
||||||
|
140 86 142
|
||||||
|
101 73 146
|
||||||
|
146 73 148
|
||||||
|
99 75 149
|
||||||
|
131 78 154
|
||||||
|
100 74 147
|
||||||
|
130 77 153
|
||||||
|
58 81 98
|
||||||
|
52 83 98
|
||||||
|
132 92 143
|
||||||
|
50 82 99
|
||||||
|
131 93 144
|
||||||
|
51 84 100
|
||||||
|
148 73 166
|
||||||
|
53 85 101
|
||||||
|
19 80 122
|
||||||
|
102 66 159
|
||||||
|
103 76 132
|
||||||
|
9 76 103
|
||||||
|
104 77 130
|
||||||
|
27 77 104
|
||||||
|
105 78 131
|
||||||
|
36 78 105
|
||||||
|
104 70 106
|
||||||
|
26 104 106
|
||||||
|
105 72 107
|
||||||
|
35 105 107
|
||||||
|
103 71 108
|
||||||
|
8 103 108
|
||||||
|
125 75 170
|
||||||
|
110 108 156
|
||||||
|
59 82 110
|
||||||
|
7 108 110
|
||||||
|
60 85 111
|
||||||
|
46 90 165
|
||||||
|
124 74 169
|
||||||
|
113 107 157
|
||||||
|
61 84 113
|
||||||
|
34 107 113
|
||||||
|
62 83 114
|
||||||
|
25 106 114
|
||||||
|
49 79 123
|
||||||
|
114 106 158
|
||||||
|
85 53 116
|
||||||
|
14 15 161
|
||||||
|
84 51 117
|
||||||
|
32 33 163
|
||||||
|
83 52 118
|
||||||
|
23 24 162
|
||||||
|
82 50 119
|
||||||
|
5 6 160
|
||||||
|
132 76 182
|
||||||
|
121 86 167
|
||||||
|
142 86 171
|
||||||
|
133 121 165
|
||||||
|
80 89 122
|
||||||
|
66 102 122
|
||||||
|
58 98 123
|
||||||
|
62 115 123
|
||||||
|
77 97 153
|
||||||
|
138 87 178
|
||||||
|
78 96 154
|
||||||
|
139 88 181
|
||||||
|
145 91 183
|
||||||
|
69 94 126
|
||||||
|
17 102 127
|
||||||
|
60 111 127
|
||||||
|
137 124 179
|
||||||
|
141 125 180
|
||||||
|
142 94 184
|
||||||
|
129 87 172
|
||||||
|
54 91 130
|
||||||
|
70 104 130
|
||||||
|
56 93 131
|
||||||
|
72 105 131
|
||||||
|
55 92 132
|
||||||
|
71 103 132
|
||||||
|
66 89 133
|
||||||
|
57 121 133
|
||||||
|
127 90 177
|
||||||
|
73 101 134
|
||||||
|
74 100 135
|
||||||
|
61 112 135
|
||||||
|
75 99 136
|
||||||
|
59 109 136
|
||||||
|
69 91 137
|
||||||
|
54 124 137
|
||||||
|
67 128 172
|
||||||
|
48 93 138
|
||||||
|
140 128 173
|
||||||
|
47 92 139
|
||||||
|
68 120 140
|
||||||
|
41 128 140
|
||||||
|
67 93 141
|
||||||
|
56 125 141
|
||||||
|
57 94 171
|
||||||
|
41 140 142
|
||||||
|
47 109 143
|
||||||
|
71 132 143
|
||||||
|
48 112 144
|
||||||
|
72 131 144
|
||||||
|
49 115 145
|
||||||
|
70 130 145
|
||||||
|
151 95 182
|
||||||
|
63 101 146
|
||||||
|
74 97 147
|
||||||
|
64 100 147
|
||||||
|
86 120 167
|
||||||
|
95 146 148
|
||||||
|
75 96 149
|
||||||
|
65 99 149
|
||||||
|
96 78 150
|
||||||
|
65 96 150
|
||||||
|
55 132 182
|
||||||
|
63 95 151
|
||||||
|
97 77 152
|
||||||
|
64 97 152
|
||||||
|
153 97 176
|
||||||
|
54 130 153
|
||||||
|
154 96 175
|
||||||
|
56 131 154
|
||||||
|
133 89 174
|
||||||
|
57 133 174
|
||||||
|
71 109 156
|
||||||
|
59 110 156
|
||||||
|
72 112 157
|
||||||
|
61 113 157
|
||||||
|
62 114 158
|
||||||
|
70 115 158
|
||||||
|
127 102 159
|
||||||
|
90 127 159
|
||||||
|
6 82 160
|
||||||
|
82 119 160
|
||||||
|
15 85 161
|
||||||
|
85 116 161
|
||||||
|
24 83 162
|
||||||
|
83 118 162
|
||||||
|
33 84 163
|
||||||
|
84 117 163
|
||||||
|
68 92 164
|
||||||
|
55 120 164
|
||||||
|
66 133 165
|
||||||
|
90 159 165
|
||||||
|
73 134 185
|
||||||
|
55 148 166
|
||||||
|
46 121 167
|
||||||
|
120 166 167
|
||||||
|
126 94 168
|
||||||
|
79 126 168
|
||||||
|
87 124 178
|
||||||
|
74 135 169
|
||||||
|
88 125 181
|
||||||
|
75 136 170
|
||||||
|
86 121 171
|
||||||
|
94 142 171
|
||||||
|
41 129 172
|
||||||
|
87 138 172
|
||||||
|
88 139 173
|
||||||
|
68 140 173
|
||||||
|
89 155 174
|
||||||
|
79 168 174
|
||||||
|
75 125 175
|
||||||
|
56 154 175
|
||||||
|
74 124 176
|
||||||
|
54 153 176
|
||||||
|
60 127 177
|
||||||
|
46 134 177
|
||||||
|
48 138 178
|
||||||
|
124 169 178
|
||||||
|
87 129 179
|
||||||
|
69 137 179
|
||||||
|
88 128 180
|
||||||
|
67 141 180
|
||||||
|
47 139 181
|
||||||
|
125 170 181
|
||||||
|
95 148 182
|
||||||
|
76 151 182
|
||||||
|
69 126 183
|
||||||
|
49 145 183
|
||||||
|
69 129 184
|
||||||
|
41 142 184
|
||||||
|
167 166 185
|
||||||
|
46 167 185
|
||||||
|
40
|
||||||
|
1 5
|
||||||
|
5 6
|
||||||
|
6 7
|
||||||
|
7 8
|
||||||
|
8 9
|
||||||
|
9 10
|
||||||
|
10 11
|
||||||
|
11 12
|
||||||
|
12 13
|
||||||
|
13 2
|
||||||
|
2 14
|
||||||
|
14 15
|
||||||
|
15 16
|
||||||
|
16 17
|
||||||
|
17 18
|
||||||
|
18 19
|
||||||
|
19 20
|
||||||
|
20 21
|
||||||
|
21 22
|
||||||
|
22 3
|
||||||
|
3 23
|
||||||
|
23 24
|
||||||
|
24 25
|
||||||
|
25 26
|
||||||
|
26 27
|
||||||
|
27 28
|
||||||
|
28 29
|
||||||
|
29 30
|
||||||
|
30 31
|
||||||
|
31 4
|
||||||
|
4 32
|
||||||
|
32 33
|
||||||
|
33 34
|
||||||
|
34 35
|
||||||
|
35 36
|
||||||
|
36 37
|
||||||
|
37 38
|
||||||
|
38 39
|
||||||
|
39 40
|
||||||
|
40 1
|
||||||
329
sheet7/E910111213/square_1_sd.txt
Normal file
329
sheet7/E910111213/square_1_sd.txt
Normal file
|
|
@ -0,0 +1,329 @@
|
||||||
|
328
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
71
sheet7/E910111213/square_2.m
Normal file
71
sheet7/E910111213/square_2.m
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
% Square:
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
% %% L-shape
|
||||||
|
% g=[2 0 2 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 1 0;
|
||||||
|
% 2 2 1 1 0.5 1 0;
|
||||||
|
% 2 1 1 0.5 2 1 0;
|
||||||
|
% 2 1 0 2 2 1 0;
|
||||||
|
% 2 0 0 2 0 1 0]';
|
||||||
|
|
||||||
|
%% square
|
||||||
|
% g=[2 0 1 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 0;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0]';
|
||||||
|
|
||||||
|
% %% 2 squares
|
||||||
|
g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 0 1 1 2;
|
||||||
|
2 1 0 1 1 1 0;
|
||||||
|
2 0 0 1 0 1 0;
|
||||||
|
2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 2 2 0 1 2 0;
|
||||||
|
2 2 1 1 1 2 0
|
||||||
|
]';
|
||||||
|
|
||||||
|
%% 4 squares
|
||||||
|
%g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 2;
|
||||||
|
% 2 1 0 1 1 1 3;
|
||||||
|
% 2 0 0 1 0 1 0;
|
||||||
|
% 2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 2 0;
|
||||||
|
% 2 2 1 1 1 2 4;
|
||||||
|
% 2 1 1 1 0 2 1;
|
||||||
|
% 2 0 1 1 1 3 1; % 3 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 1 2 3 4;
|
||||||
|
% 2 1 0 2 2 3 0;
|
||||||
|
% 2 0 0 2 1 3 0;
|
||||||
|
% 2 1 2 1 1 4 2; % 4 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 1 2 4 0;
|
||||||
|
% 2 2 1 2 2 4 0
|
||||||
|
% 2 1 1 2 1 4 3
|
||||||
|
% ]';
|
||||||
|
|
||||||
|
[p,e,t] = initmesh(g,'hmax',0.1);
|
||||||
|
pdemesh(p,e,t)
|
||||||
|
|
||||||
|
%% GH
|
||||||
|
% output from <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>
|
||||||
|
%
|
||||||
|
% coordinates p: [2][nnode]
|
||||||
|
% connectivity t: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
|
||||||
|
ascii_write_mesh( p, t, e, mfilename);
|
||||||
|
|
||||||
|
ascii_write_subdomains( p, t, e, mfilename);
|
||||||
|
|
||||||
|
|
||||||
|
% tmp=t(1:3,:)
|
||||||
|
|
||||||
1086
sheet7/E910111213/square_2.txt
Normal file
1086
sheet7/E910111213/square_2.txt
Normal file
File diff suppressed because it is too large
Load diff
653
sheet7/E910111213/square_2_sd.txt
Normal file
653
sheet7/E910111213/square_2_sd.txt
Normal file
|
|
@ -0,0 +1,653 @@
|
||||||
|
652
|
||||||
|
1
|
||||||
|
2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
1
|
||||||
71
sheet7/E910111213/square_4.m
Normal file
71
sheet7/E910111213/square_4.m
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
% Square:
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
% %% L-shape
|
||||||
|
% g=[2 0 2 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 1 0;
|
||||||
|
% 2 2 1 1 0.5 1 0;
|
||||||
|
% 2 1 1 0.5 2 1 0;
|
||||||
|
% 2 1 0 2 2 1 0;
|
||||||
|
% 2 0 0 2 0 1 0]';
|
||||||
|
|
||||||
|
%% square
|
||||||
|
% g=[2 0 1 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 0;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0]';
|
||||||
|
|
||||||
|
% %% 2 squares
|
||||||
|
% g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 2;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0;
|
||||||
|
% 2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 2 0;
|
||||||
|
% 2 2 1 1 1 2 0
|
||||||
|
% ]';
|
||||||
|
|
||||||
|
%% 4 squares
|
||||||
|
g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 0 1 1 2;
|
||||||
|
2 1 0 1 1 1 3;
|
||||||
|
2 0 0 1 0 1 0;
|
||||||
|
2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 2 2 0 1 2 0;
|
||||||
|
2 2 1 1 1 2 4;
|
||||||
|
% 2 1 1 1 0 2 1;
|
||||||
|
% 2 0 1 1 1 3 1; % 3 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 1 2 3 4;
|
||||||
|
2 1 0 2 2 3 0;
|
||||||
|
2 0 0 2 1 3 0;
|
||||||
|
% 2 1 2 1 1 4 2; % 4 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 2 2 1 2 4 0;
|
||||||
|
2 2 1 2 2 4 0
|
||||||
|
% 2 1 1 2 1 4 3
|
||||||
|
]';
|
||||||
|
|
||||||
|
[p,e,t] = initmesh(g,'hmax',0.1);
|
||||||
|
pdemesh(p,e,t)
|
||||||
|
|
||||||
|
%% GH
|
||||||
|
% output from <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>
|
||||||
|
%
|
||||||
|
% coordinates p: [2][nnode]
|
||||||
|
% connectivity t: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
|
||||||
|
ascii_write_mesh( p, t, e, mfilename);
|
||||||
|
|
||||||
|
ascii_write_subdomains( p, t, e, mfilename);
|
||||||
|
|
||||||
|
|
||||||
|
% tmp=t(1:3,:)
|
||||||
|
|
||||||
BIN
sheet7/E910111213/square_4.pdf
Normal file
BIN
sheet7/E910111213/square_4.pdf
Normal file
Binary file not shown.
2176
sheet7/E910111213/square_4.txt
Normal file
2176
sheet7/E910111213/square_4.txt
Normal file
File diff suppressed because it is too large
Load diff
1335
sheet7/E910111213/square_4_sd.txt
Normal file
1335
sheet7/E910111213/square_4_sd.txt
Normal file
File diff suppressed because it is too large
Load diff
705
sheet7/E910111213/uv.txt
Normal file
705
sheet7/E910111213/uv.txt
Normal file
|
|
@ -0,0 +1,705 @@
|
||||||
|
187 2 330 3
|
||||||
|
0 0
|
||||||
|
1 0
|
||||||
|
1 1
|
||||||
|
0 1
|
||||||
|
0.1 0
|
||||||
|
0.2 0
|
||||||
|
0.3 0
|
||||||
|
0.4 0
|
||||||
|
0.5 0
|
||||||
|
0.6 0
|
||||||
|
0.7 0
|
||||||
|
0.8 0
|
||||||
|
0.9 0
|
||||||
|
1 0.1
|
||||||
|
1 0.2
|
||||||
|
1 0.3
|
||||||
|
1 0.4
|
||||||
|
1 0.5
|
||||||
|
1 0.6
|
||||||
|
1 0.7
|
||||||
|
1 0.8
|
||||||
|
1 0.9
|
||||||
|
0.9 1
|
||||||
|
0.8 1
|
||||||
|
0.7 1
|
||||||
|
0.6 1
|
||||||
|
0.5 1
|
||||||
|
0.4 1
|
||||||
|
0.3 1
|
||||||
|
0.2 1
|
||||||
|
0.1 1
|
||||||
|
0 0.9
|
||||||
|
0 0.8
|
||||||
|
0 0.7
|
||||||
|
0 0.6
|
||||||
|
0 0.5
|
||||||
|
0 0.4
|
||||||
|
0 0.3
|
||||||
|
0 0.2
|
||||||
|
0 0.1
|
||||||
|
0.479684 0.513096
|
||||||
|
0.0481001 0.0438139
|
||||||
|
0.965456 0.0484346
|
||||||
|
0.0438168 0.951897
|
||||||
|
0.961962 0.955138
|
||||||
|
0.754828 0.354966
|
||||||
|
0.360392 0.264508
|
||||||
|
0.267426 0.637353
|
||||||
|
0.65649 0.728531
|
||||||
|
0.0895934 0.160441
|
||||||
|
0.160484 0.910354
|
||||||
|
0.911842 0.844141
|
||||||
|
0.841625 0.0900995
|
||||||
|
0.451559 0.770056
|
||||||
|
0.557953 0.236427
|
||||||
|
0.229318 0.453048
|
||||||
|
0.687178 0.534082
|
||||||
|
0.814675 0.688238
|
||||||
|
0.258637 0.157666
|
||||||
|
0.852304 0.258371
|
||||||
|
0.158327 0.741011
|
||||||
|
0.745783 0.841799
|
||||||
|
0.734225 0.0924118
|
||||||
|
0.266805 0.909841
|
||||||
|
0.0900392 0.266867
|
||||||
|
0.845906 0.489216
|
||||||
|
0.340275 0.504784
|
||||||
|
0.482979 0.335446
|
||||||
|
0.532713 0.650471
|
||||||
|
0.609686 0.857218
|
||||||
|
0.390369 0.135169
|
||||||
|
0.137445 0.608961
|
||||||
|
0.711137 0.231036
|
||||||
|
0.311055 0.779038
|
||||||
|
0.220383 0.310202
|
||||||
|
0.542551 0.0753476
|
||||||
|
0.442762 0.912027
|
||||||
|
0.0870955 0.443563
|
||||||
|
0.71891 0.663674
|
||||||
|
0.911087 0.643693
|
||||||
|
0.910368 0.745257
|
||||||
|
0.175659 0.104224
|
||||||
|
0.826322 0.898216
|
||||||
|
0.104383 0.824244
|
||||||
|
0.899601 0.174158
|
||||||
|
0.605353 0.422553
|
||||||
|
0.396664 0.624664
|
||||||
|
0.371373 0.387899
|
||||||
|
0.824327 0.584766
|
||||||
|
0.825103 0.373429
|
||||||
|
0.524606 0.742235
|
||||||
|
0.459558 0.258909
|
||||||
|
0.261176 0.536509
|
||||||
|
0.606947 0.570757
|
||||||
|
0.662867 0.13484
|
||||||
|
0.141276 0.353323
|
||||||
|
0.353003 0.858305
|
||||||
|
0.824585 0.795396
|
||||||
|
0.180506 0.217545
|
||||||
|
0.217867 0.81926
|
||||||
|
0.7886 0.183202
|
||||||
|
0.920145 0.449301
|
||||||
|
0.445028 0.0729222
|
||||||
|
0.552084 0.922007
|
||||||
|
0.0761805 0.552601
|
||||||
|
0.646019 0.929394
|
||||||
|
0.0688853 0.645563
|
||||||
|
0.353835 0.0678044
|
||||||
|
0.33465 0.18669
|
||||||
|
0.267936 0.0754627
|
||||||
|
0.930563 0.255545
|
||||||
|
0.188297 0.664536
|
||||||
|
0.0758775 0.731844
|
||||||
|
0.733221 0.923739
|
||||||
|
0.670883 0.805934
|
||||||
|
0.927247 0.0922677
|
||||||
|
0.0754421 0.907509
|
||||||
|
0.909844 0.925626
|
||||||
|
0.0924729 0.0754185
|
||||||
|
0.568222 0.332532
|
||||||
|
0.700102 0.44222
|
||||||
|
0.916968 0.544333
|
||||||
|
0.738541 0.754101
|
||||||
|
0.388485 0.711156
|
||||||
|
0.287351 0.384911
|
||||||
|
0.629832 0.654561
|
||||||
|
0.900814 0.346453
|
||||||
|
0.41132 0.456786
|
||||||
|
0.465434 0.593118
|
||||||
|
0.514562 0.831523
|
||||||
|
0.16528 0.517016
|
||||||
|
0.484085 0.160379
|
||||||
|
0.76514 0.511037
|
||||||
|
0.772882 0.273336
|
||||||
|
0.241297 0.724487
|
||||||
|
0.274741 0.24004
|
||||||
|
0.469165 0.706885
|
||||||
|
0.334436 0.584171
|
||||||
|
0.409135 0.327415
|
||||||
|
0.506546 0.420168
|
||||||
|
0.291267 0.463861
|
||||||
|
0.560193 0.497192
|
||||||
|
0.405521 0.200759
|
||||||
|
0.203388 0.593306
|
||||||
|
0.593803 0.779935
|
||||||
|
0.708431 0.167068
|
||||||
|
0.286576 0.842217
|
||||||
|
0.645259 0.197405
|
||||||
|
0.157539 0.286478
|
||||||
|
0.0634282 0.35253
|
||||||
|
0.638015 0.0744131
|
||||||
|
0.352255 0.936338
|
||||||
|
0.429132 0.833285
|
||||||
|
0.1657 0.430369
|
||||||
|
0.774817 0.630926
|
||||||
|
0.320743 0.124262
|
||||||
|
0.125322 0.678789
|
||||||
|
0.681128 0.871955
|
||||||
|
0.856775 0.417367
|
||||||
|
0.141959 0.0447961
|
||||||
|
0.956726 0.141515
|
||||||
|
0.859027 0.95601
|
||||||
|
0.0448254 0.858021
|
||||||
|
0.51729 0.290331
|
||||||
|
0.791421 0.430793
|
||||||
|
0.642597 0.273685
|
||||||
|
0.663496 0.353015
|
||||||
|
0.676853 0.601987
|
||||||
|
0.308734 0.701655
|
||||||
|
0.297005 0.306339
|
||||||
|
0.632153 0.492996
|
||||||
|
0.404572 0.546354
|
||||||
|
0.436385 0.385368
|
||||||
|
0.741254 0.587512
|
||||||
|
0.208229 0.386035
|
||||||
|
0.386065 0.791119
|
||||||
|
0.821222 0.320652
|
||||||
|
0.33864 0.652457
|
||||||
|
0.450215 0.657712
|
||||||
|
0.340125 0.439662
|
||||||
|
0.344719 0.333947
|
||||||
|
0.588452 0.145922
|
||||||
|
0.587363 0.711465
|
||||||
|
0.529103 0.564926
|
||||||
|
0.709038 0.296367
|
||||||
|
1 0.95
|
||||||
|
1 0.05
|
||||||
|
13 2 43
|
||||||
|
82 6 110
|
||||||
|
7 8 108
|
||||||
|
43 2 187
|
||||||
|
42 5 119
|
||||||
|
119 5 160
|
||||||
|
6 7 110
|
||||||
|
92 47 143
|
||||||
|
9 10 76
|
||||||
|
76 10 151
|
||||||
|
31 4 44
|
||||||
|
85 15 111
|
||||||
|
111 16 127
|
||||||
|
17 18 102
|
||||||
|
102 18 122
|
||||||
|
12 13 53
|
||||||
|
53 13 116
|
||||||
|
43 14 116
|
||||||
|
15 16 111
|
||||||
|
40 1 42
|
||||||
|
134 46 185
|
||||||
|
21 22 52
|
||||||
|
83 24 114
|
||||||
|
25 26 106
|
||||||
|
52 22 118
|
||||||
|
45 23 118
|
||||||
|
24 25 114
|
||||||
|
126 49 183
|
||||||
|
27 28 77
|
||||||
|
77 28 152
|
||||||
|
30 31 51
|
||||||
|
51 31 117
|
||||||
|
44 32 117
|
||||||
|
84 33 113
|
||||||
|
33 34 113
|
||||||
|
34 35 107
|
||||||
|
1 5 42
|
||||||
|
50 40 119
|
||||||
|
3 23 45
|
||||||
|
93 48 144
|
||||||
|
36 37 78
|
||||||
|
78 37 150
|
||||||
|
39 40 50
|
||||||
|
116 14 161
|
||||||
|
4 32 44
|
||||||
|
117 32 163
|
||||||
|
118 23 162
|
||||||
|
45 22 186
|
||||||
|
19 20 80
|
||||||
|
128 41 172
|
||||||
|
166 73 185
|
||||||
|
16 17 127
|
||||||
|
129 41 184
|
||||||
|
8 9 103
|
||||||
|
138 67 172
|
||||||
|
35 36 105
|
||||||
|
40 42 119
|
||||||
|
170 47 181
|
||||||
|
31 44 117
|
||||||
|
169 48 178
|
||||||
|
22 45 118
|
||||||
|
26 27 104
|
||||||
|
13 43 116
|
||||||
|
115 49 123
|
||||||
|
135 48 169
|
||||||
|
29 30 64
|
||||||
|
136 47 170
|
||||||
|
11 12 63
|
||||||
|
79 49 126
|
||||||
|
38 39 65
|
||||||
|
92 55 164
|
||||||
|
94 57 168
|
||||||
|
80 20 81
|
||||||
|
168 57 174
|
||||||
|
109 47 136
|
||||||
|
39 50 65
|
||||||
|
90 46 177
|
||||||
|
12 53 63
|
||||||
|
112 48 135
|
||||||
|
30 51 64
|
||||||
|
20 21 81
|
||||||
|
79 58 123
|
||||||
|
63 53 101
|
||||||
|
139 68 173
|
||||||
|
64 51 100
|
||||||
|
91 54 137
|
||||||
|
65 50 99
|
||||||
|
93 56 141
|
||||||
|
21 52 81
|
||||||
|
121 46 165
|
||||||
|
124 54 176
|
||||||
|
125 56 175
|
||||||
|
148 55 182
|
||||||
|
128 88 173
|
||||||
|
121 57 171
|
||||||
|
93 67 138
|
||||||
|
28 29 152
|
||||||
|
115 62 158
|
||||||
|
10 11 151
|
||||||
|
109 59 156
|
||||||
|
37 38 150
|
||||||
|
112 61 157
|
||||||
|
85 60 101
|
||||||
|
120 55 166
|
||||||
|
84 61 100
|
||||||
|
97 74 176
|
||||||
|
82 59 99
|
||||||
|
96 75 175
|
||||||
|
120 68 164
|
||||||
|
11 63 151
|
||||||
|
129 69 179
|
||||||
|
29 64 152
|
||||||
|
128 67 180
|
||||||
|
38 65 150
|
||||||
|
80 58 89
|
||||||
|
91 69 183
|
||||||
|
81 52 98
|
||||||
|
89 58 155
|
||||||
|
98 62 123
|
||||||
|
58 80 81
|
||||||
|
96 65 149
|
||||||
|
108 71 156
|
||||||
|
83 62 98
|
||||||
|
106 70 158
|
||||||
|
97 64 147
|
||||||
|
107 72 157
|
||||||
|
95 63 146
|
||||||
|
134 60 177
|
||||||
|
159 66 165
|
||||||
|
120 86 140
|
||||||
|
94 69 184
|
||||||
|
124 87 179
|
||||||
|
92 68 139
|
||||||
|
125 88 180
|
||||||
|
58 79 155
|
||||||
|
18 19 122
|
||||||
|
101 60 134
|
||||||
|
89 66 122
|
||||||
|
115 70 145
|
||||||
|
130 91 145
|
||||||
|
99 59 136
|
||||||
|
109 71 143
|
||||||
|
100 61 135
|
||||||
|
112 72 144
|
||||||
|
155 79 174
|
||||||
|
140 86 142
|
||||||
|
101 73 146
|
||||||
|
146 73 148
|
||||||
|
99 75 149
|
||||||
|
131 78 154
|
||||||
|
100 74 147
|
||||||
|
130 77 153
|
||||||
|
58 81 98
|
||||||
|
52 83 98
|
||||||
|
132 92 143
|
||||||
|
50 82 99
|
||||||
|
131 93 144
|
||||||
|
51 84 100
|
||||||
|
148 73 166
|
||||||
|
53 85 101
|
||||||
|
19 80 122
|
||||||
|
102 66 159
|
||||||
|
103 76 132
|
||||||
|
9 76 103
|
||||||
|
104 77 130
|
||||||
|
27 77 104
|
||||||
|
105 78 131
|
||||||
|
36 78 105
|
||||||
|
104 70 106
|
||||||
|
26 104 106
|
||||||
|
105 72 107
|
||||||
|
35 105 107
|
||||||
|
103 71 108
|
||||||
|
8 103 108
|
||||||
|
125 75 170
|
||||||
|
110 108 156
|
||||||
|
59 82 110
|
||||||
|
7 108 110
|
||||||
|
60 85 111
|
||||||
|
46 90 165
|
||||||
|
124 74 169
|
||||||
|
113 107 157
|
||||||
|
61 84 113
|
||||||
|
34 107 113
|
||||||
|
62 83 114
|
||||||
|
25 106 114
|
||||||
|
49 79 123
|
||||||
|
114 106 158
|
||||||
|
85 53 116
|
||||||
|
14 15 161
|
||||||
|
84 51 117
|
||||||
|
32 33 163
|
||||||
|
83 52 118
|
||||||
|
23 24 162
|
||||||
|
82 50 119
|
||||||
|
5 6 160
|
||||||
|
132 76 182
|
||||||
|
121 86 167
|
||||||
|
142 86 171
|
||||||
|
133 121 165
|
||||||
|
80 89 122
|
||||||
|
66 102 122
|
||||||
|
58 98 123
|
||||||
|
62 115 123
|
||||||
|
77 97 153
|
||||||
|
138 87 178
|
||||||
|
78 96 154
|
||||||
|
139 88 181
|
||||||
|
145 91 183
|
||||||
|
69 94 126
|
||||||
|
17 102 127
|
||||||
|
60 111 127
|
||||||
|
137 124 179
|
||||||
|
141 125 180
|
||||||
|
142 94 184
|
||||||
|
129 87 172
|
||||||
|
54 91 130
|
||||||
|
70 104 130
|
||||||
|
56 93 131
|
||||||
|
72 105 131
|
||||||
|
55 92 132
|
||||||
|
71 103 132
|
||||||
|
66 89 133
|
||||||
|
57 121 133
|
||||||
|
127 90 177
|
||||||
|
73 101 134
|
||||||
|
74 100 135
|
||||||
|
61 112 135
|
||||||
|
75 99 136
|
||||||
|
59 109 136
|
||||||
|
69 91 137
|
||||||
|
54 124 137
|
||||||
|
67 128 172
|
||||||
|
48 93 138
|
||||||
|
140 128 173
|
||||||
|
47 92 139
|
||||||
|
68 120 140
|
||||||
|
41 128 140
|
||||||
|
67 93 141
|
||||||
|
56 125 141
|
||||||
|
57 94 171
|
||||||
|
41 140 142
|
||||||
|
47 109 143
|
||||||
|
71 132 143
|
||||||
|
48 112 144
|
||||||
|
72 131 144
|
||||||
|
49 115 145
|
||||||
|
70 130 145
|
||||||
|
151 95 182
|
||||||
|
63 101 146
|
||||||
|
74 97 147
|
||||||
|
64 100 147
|
||||||
|
86 120 167
|
||||||
|
95 146 148
|
||||||
|
75 96 149
|
||||||
|
65 99 149
|
||||||
|
96 78 150
|
||||||
|
65 96 150
|
||||||
|
55 132 182
|
||||||
|
63 95 151
|
||||||
|
97 77 152
|
||||||
|
64 97 152
|
||||||
|
153 97 176
|
||||||
|
54 130 153
|
||||||
|
154 96 175
|
||||||
|
56 131 154
|
||||||
|
133 89 174
|
||||||
|
57 133 174
|
||||||
|
71 109 156
|
||||||
|
59 110 156
|
||||||
|
72 112 157
|
||||||
|
61 113 157
|
||||||
|
62 114 158
|
||||||
|
70 115 158
|
||||||
|
127 102 159
|
||||||
|
90 127 159
|
||||||
|
6 82 160
|
||||||
|
82 119 160
|
||||||
|
15 85 161
|
||||||
|
85 116 161
|
||||||
|
24 83 162
|
||||||
|
83 118 162
|
||||||
|
33 84 163
|
||||||
|
84 117 163
|
||||||
|
68 92 164
|
||||||
|
55 120 164
|
||||||
|
66 133 165
|
||||||
|
90 159 165
|
||||||
|
73 134 185
|
||||||
|
55 148 166
|
||||||
|
46 121 167
|
||||||
|
120 166 167
|
||||||
|
126 94 168
|
||||||
|
79 126 168
|
||||||
|
87 124 178
|
||||||
|
74 135 169
|
||||||
|
88 125 181
|
||||||
|
75 136 170
|
||||||
|
86 121 171
|
||||||
|
94 142 171
|
||||||
|
41 129 172
|
||||||
|
87 138 172
|
||||||
|
88 139 173
|
||||||
|
68 140 173
|
||||||
|
89 155 174
|
||||||
|
79 168 174
|
||||||
|
75 125 175
|
||||||
|
56 154 175
|
||||||
|
74 124 176
|
||||||
|
54 153 176
|
||||||
|
60 127 177
|
||||||
|
46 134 177
|
||||||
|
48 138 178
|
||||||
|
124 169 178
|
||||||
|
87 129 179
|
||||||
|
69 137 179
|
||||||
|
88 128 180
|
||||||
|
67 141 180
|
||||||
|
47 139 181
|
||||||
|
125 170 181
|
||||||
|
95 148 182
|
||||||
|
76 151 182
|
||||||
|
69 126 183
|
||||||
|
49 145 183
|
||||||
|
69 129 184
|
||||||
|
41 142 184
|
||||||
|
167 166 185
|
||||||
|
46 167 185
|
||||||
|
3 45 186
|
||||||
|
14 43 187
|
||||||
|
0
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
135
sheet7/E910111213/vdop.cpp
Normal file
135
sheet7/E910111213/vdop.cpp
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
#include "vdop.h"
|
||||||
|
#include <cassert> // assert()
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
void vddiv(vector<double> & x, vector<double> const& y,
|
||||||
|
vector<double> const& z)
|
||||||
|
{
|
||||||
|
assert( x.size()==y.size() && y.size()==z.size() );
|
||||||
|
size_t n = x.size();
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (size_t k = 0; k < n; ++k)
|
||||||
|
{
|
||||||
|
x[k] = y[k] / z[k];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
|
||||||
|
void vdaxpy(std::vector<double> & x, std::vector<double> const& y,
|
||||||
|
double alpha, std::vector<double> const& z )
|
||||||
|
{
|
||||||
|
assert( x.size()==y.size() && y.size()==z.size() );
|
||||||
|
size_t n = x.size();
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (size_t k = 0; k < n; ++k)
|
||||||
|
{
|
||||||
|
x[k] = y[k] + alpha * z[k];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//******************************************************************************
|
||||||
|
|
||||||
|
double dscapr(std::vector<double> const& x, std::vector<double> const& y)
|
||||||
|
{
|
||||||
|
assert( x.size()==y.size());
|
||||||
|
size_t n = x.size();
|
||||||
|
|
||||||
|
double s = 0.0;
|
||||||
|
//#pragma omp parallel for reduction(+:s)
|
||||||
|
for (size_t k = 0; k < n; ++k)
|
||||||
|
{
|
||||||
|
s += x[k] * y[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
//void DebugVector(vector<double> const &v)
|
||||||
|
//{
|
||||||
|
//cout << "\nVector (nnode = " << v.size() << ")\n";
|
||||||
|
//for (size_t j = 0; j < v.size(); ++j)
|
||||||
|
//{
|
||||||
|
//cout.setf(ios::right, ios::adjustfield);
|
||||||
|
//cout << v[j] << " ";
|
||||||
|
//}
|
||||||
|
//cout << endl;
|
||||||
|
|
||||||
|
//return;
|
||||||
|
//}
|
||||||
|
//******************************************************************************
|
||||||
|
bool CompareVectors(std::vector<double> const& x, int const n, double const y[], double const eps)
|
||||||
|
{
|
||||||
|
bool bn = (static_cast<int>(x.size())==n);
|
||||||
|
if (!bn)
|
||||||
|
{
|
||||||
|
cout << "######### Error: " << "number of elements" << endl;
|
||||||
|
}
|
||||||
|
//bool bv = equal(x.cbegin(),x.cend(),y);
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y,
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
if (!bv)
|
||||||
|
{
|
||||||
|
assert(static_cast<int>(x.size())==n);
|
||||||
|
cout << "######### Error: " << "values" << endl;
|
||||||
|
}
|
||||||
|
return bn && bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
double par_scalar(vector<double> const &x, vector<double> const &y, MPI_Comm const& icomm)
|
||||||
|
{
|
||||||
|
const double s = dscapr(x,y);
|
||||||
|
double sg;
|
||||||
|
MPI_Allreduce(&s,&sg,1,MPI_DOUBLE,MPI_SUM,icomm);
|
||||||
|
|
||||||
|
return(sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
void ExchangeAll(vector<double> const &xin, vector<double> &yout, MPI_Comm const &icomm)
|
||||||
|
{
|
||||||
|
int myrank, numprocs,ierr(-1);
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
int const N=xin.size();
|
||||||
|
int const sendcount = N/numprocs; // equal sized junks
|
||||||
|
assert(sendcount*numprocs==N); // really all junk sized?
|
||||||
|
assert(xin.size()==yout.size());
|
||||||
|
|
||||||
|
auto sendbuf = xin.data();
|
||||||
|
auto recvbuf = yout.data();
|
||||||
|
ierr = MPI_Alltoall(sendbuf, sendcount, MPI_DOUBLE,
|
||||||
|
recvbuf, sendcount, MPI_DOUBLE, icomm);
|
||||||
|
assert(0==ierr);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
void ExchangeAllInPlace(vector<double> &xin, MPI_Comm const &icomm)
|
||||||
|
{
|
||||||
|
int myrank, numprocs,ierr(-1);
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
int const N=xin.size();
|
||||||
|
int const sendcount = N/numprocs; // equal sized junks
|
||||||
|
assert(sendcount*numprocs==N); // really all junk sized?
|
||||||
|
|
||||||
|
auto sendbuf = xin.data();
|
||||||
|
ierr = MPI_Alltoall(MPI_IN_PLACE, sendcount, MPI_DOUBLE,
|
||||||
|
sendbuf, sendcount, MPI_DOUBLE, icomm);
|
||||||
|
assert(0==ierr);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
166
sheet7/E910111213/vdop.h
Normal file
166
sheet7/E910111213/vdop.h
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
#ifndef VDOP_FILE
|
||||||
|
#define VDOP_FILE
|
||||||
|
#include <iostream>
|
||||||
|
#include <mpi.h> // MPI
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/** @brief Element-wise vector divison x_k = y_k/z_k.
|
||||||
|
*
|
||||||
|
* @param[out] x target vector
|
||||||
|
* @param[in] y source vector
|
||||||
|
* @param[in] z source vector
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void vddiv(std::vector<double> &x, std::vector<double> const &y,
|
||||||
|
std::vector<double> const &z);
|
||||||
|
|
||||||
|
/** @brief Element-wise daxpy operation x(k) = y(k) + alpha*z(k).
|
||||||
|
*
|
||||||
|
* @param[out] x target vector
|
||||||
|
* @param[in] y source vector
|
||||||
|
* @param[in] alpha scalar
|
||||||
|
* @param[in] z source vector
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void vdaxpy(std::vector<double> &x, std::vector<double> const &y,
|
||||||
|
double alpha, std::vector<double> const &z );
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Calculates the Euclidean inner product of two vectors.
|
||||||
|
*
|
||||||
|
* @param[in] x vector
|
||||||
|
* @param[in] y vector
|
||||||
|
* @return Euclidean inner product @f$\langle x,y \rangle@f$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
double dscapr(std::vector<double> const &x, std::vector<double> const &y);
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
double L2_scapr(std::vector<double> const &x, std::vector<double> const &y)
|
||||||
|
{
|
||||||
|
return dscapr(x, y) / x.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Parallel inner product
|
||||||
|
@param[in] x vector
|
||||||
|
@param[in] y vector
|
||||||
|
@param[in] icomm MPI communicator
|
||||||
|
@return resulting Euclidian inner product <x,y>
|
||||||
|
*/
|
||||||
|
double par_scalar(std::vector<double> const &x, std::vector<double> const &y,
|
||||||
|
MPI_Comm const& icomm=MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ReadId : Input and broadcast of an integer */
|
||||||
|
inline
|
||||||
|
int ReadIn(std::string const &ss = std::string(), MPI_Comm const &icomm = MPI_COMM_WORLD)
|
||||||
|
{
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
int myrank; /* my rank number */
|
||||||
|
MPI_Comm_rank(icomm, &myrank);
|
||||||
|
int id;
|
||||||
|
|
||||||
|
if (myrank == 0) {
|
||||||
|
std::cout << "\n\n " << ss << " : Which process do you want to debug ? \n";
|
||||||
|
std::cin >> id;
|
||||||
|
}
|
||||||
|
MPI_Bcast(&id, 1, MPI_INT, 0, icomm);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print entries of a vector to standard output.
|
||||||
|
*
|
||||||
|
* @param[in] v vector values
|
||||||
|
* @param[in] ss string containing the vector name
|
||||||
|
* @param[in] icomm communicator group for MPI
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//void DebugVector(std::vector<double> const &v);
|
||||||
|
template <class T>
|
||||||
|
void DebugVector(std::vector<T> const &v, std::string const &ss = std::string(), MPI_Comm const &icomm = MPI_COMM_WORLD)
|
||||||
|
{
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
int numprocs; /* # processes */
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
int myrank; /* my rank number */
|
||||||
|
MPI_Comm_rank(icomm, &myrank);
|
||||||
|
|
||||||
|
int readid = ReadIn(ss); /* Read readid */
|
||||||
|
|
||||||
|
while ( (0 <= readid) && (readid < numprocs) ) {
|
||||||
|
if (myrank == readid) {
|
||||||
|
std::cout << "\n\n process " << readid;
|
||||||
|
std::cout << "\n .... " << ss << " (nnode = " << v.size() << ")\n";
|
||||||
|
for (size_t j = 0; j < v.size(); ++j) {
|
||||||
|
std::cout.setf(std::ios::right, std::ios::adjustfield);
|
||||||
|
std::cout << v[j] << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
readid = ReadIn(ss, icomm); /* Read readid */
|
||||||
|
}
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Compares an STL vector with POD vector.
|
||||||
|
*
|
||||||
|
* The accuracy criteria @f$ |x_k-y_k| < \varepsilon \left({1+0.5(|x_k|+|y_k|)}\right) @f$
|
||||||
|
* follows the book by
|
||||||
|
* <a href="https://www.springer.com/la/book/9783319446592">Stoyan/Baran</a>, p.8.
|
||||||
|
*
|
||||||
|
* @param[in] x STL vector
|
||||||
|
* @param[in] n length of POD vector
|
||||||
|
* @param[in] y POD vector
|
||||||
|
* @param[in] eps relative accuracy criteria (default := 0.0).
|
||||||
|
* @return true iff pairwise vector elements are relatively close to each other.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool CompareVectors(std::vector<double> const &x, int n, double const y[], double const eps = 0.0);
|
||||||
|
|
||||||
|
|
||||||
|
/** Output operator for vector
|
||||||
|
* @param[in,out] s output stream, e.g. @p cout
|
||||||
|
* @param[in] v vector
|
||||||
|
*
|
||||||
|
* @return output stream
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
std::ostream &operator<<(std::ostream &s, std::vector<T> const &v)
|
||||||
|
{
|
||||||
|
for (auto vp : v) {
|
||||||
|
s << vp << " ";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Exchanges equal size partions of vector @p xin with all MPI processes.
|
||||||
|
* The received data are return in vector @p yout .
|
||||||
|
*
|
||||||
|
* @param[in] xin input vector
|
||||||
|
* @param[out] yout output vector
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ExchangeAll(std::vector<double> const &xin, std::vector<double> &yout, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
/** Exchanges equal size partions of vector @p xin with all MPI processes.
|
||||||
|
* The received data are return in vector @p xin .
|
||||||
|
*
|
||||||
|
* @param[in,out] xin input/output vector
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ExchangeAllInPlace(std::vector<double> &xin, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
20
sheet7/E910111213/visualize_results.m
Normal file
20
sheet7/E910111213/visualize_results.m
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
%% Visualize results
|
||||||
|
%
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
%
|
||||||
|
% or
|
||||||
|
% matlab -nosplash < <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
|
||||||
|
%%
|
||||||
|
fname = 'uv.txt';
|
||||||
|
|
||||||
|
[xc,ia,v] = ascii_read_meshvector(fname);
|
||||||
|
|
||||||
|
h = trisurf(ia, xc(:,1), xc(:,2), v);
|
||||||
|
|
||||||
|
waitfor(h) % wait for closing the figure
|
||||||
154
sheet7/GCC_default.mk
Normal file
154
sheet7/GCC_default.mk
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
# Basic Defintions for using GNU-compiler suite sequentially
|
||||||
|
# requires setting of COMPILER=GCC_
|
||||||
|
|
||||||
|
#startmake as follows to avoid warnings caused by OpenMPI code
|
||||||
|
# make 2>&1 | grep -v openmpi
|
||||||
|
|
||||||
|
|
||||||
|
MPI_ROOT=/usr/bin/
|
||||||
|
|
||||||
|
CC = ${MPI_ROOT}mpicc
|
||||||
|
CXX = ${MPI_ROOT}mpicxx
|
||||||
|
F77 = ${MPI_ROOT}mpif77
|
||||||
|
LINKER = ${CXX}
|
||||||
|
|
||||||
|
# If you 'mpirun ...' reports some error "... not enough slots .." then use the option '--oversubscribe'
|
||||||
|
MPIRUN = ${MPI_ROOT}mpirun --oversubscribe -display-map
|
||||||
|
#MPIRUN = ${MPI_ROOT}mpiexec
|
||||||
|
|
||||||
|
# 2023, Oct 23: ""WARNING: There is at least non-excluded one OpenFabrics device found,"
|
||||||
|
# solution according to https://github.com/open-mpi/ompi/issues/11063
|
||||||
|
MPIRUN += -mca btl ^openib
|
||||||
|
|
||||||
|
# KFU:sauron
|
||||||
|
CXXFLAGS += -I/software/boost/1_72_0/include
|
||||||
|
|
||||||
|
WARNINGS = -Wall -pedantic -Woverloaded-virtual -Wfloat-equal -Wshadow \
|
||||||
|
-Wredundant-decls -Wunreachable-code -Winline -fmax-errors=1
|
||||||
|
|
||||||
|
# WARNINGS += -Weffc++ -Wextra
|
||||||
|
# -Wno-pragmas
|
||||||
|
CXXFLAGS += -std=c++17 -ffast-math -O3 -march=native ${WARNINGS}
|
||||||
|
# -ftree-vectorizer-verbose=5 -DNDEBUG
|
||||||
|
# -ftree-vectorizer-verbose=2
|
||||||
|
# CFLAGS = -ffast-math -O3 -DNDEBUG -msse3 -fopenmp -fdump-tree-vect-details
|
||||||
|
# CFLAGS = -ffast-math -O3 -funroll-loops -DNDEBUG -msse3 -fopenmp -ftree-vectorizer-verbose=2
|
||||||
|
|
||||||
|
# info on vectorization
|
||||||
|
#VECTORIZE = -ftree-vectorize -fdump-tree-vect-blocks=foo.dump
|
||||||
|
#-fdump-tree-pre=stderr
|
||||||
|
VECTORIZE = -ftree-vectorize -fopt-info -ftree-vectorizer-verbose=5
|
||||||
|
#CXXFLAGS += ${VECTORIZE}
|
||||||
|
|
||||||
|
# -funroll-all-loops -msse3
|
||||||
|
#GCC -march=knl -march=broadwell -march=haswell
|
||||||
|
|
||||||
|
# for debugging purpose (save code)
|
||||||
|
# -fsanitize=leak # only one out the trhee can be used
|
||||||
|
# -fsanitize=address
|
||||||
|
# -fsanitize=thread
|
||||||
|
SANITARY = -fsanitize=address -fsanitize=undefined -fsanitize=null -fsanitize=return \
|
||||||
|
-fsanitize=bounds -fsanitize=alignment -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow \
|
||||||
|
-fsanitize=bool -fsanitize=enum -fsanitize=vptr
|
||||||
|
#CXXFLAGS += ${SANITARY}
|
||||||
|
#LINKFLAGS +=${SANITARY}
|
||||||
|
|
||||||
|
# OpenMP
|
||||||
|
CXXFLAGS += -fopenmp
|
||||||
|
LINKFLAGS += -fopenmp
|
||||||
|
|
||||||
|
default: ${PROGRAM}
|
||||||
|
|
||||||
|
${PROGRAM}: ${OBJECTS}
|
||||||
|
$(LINKER) $^ ${LINKFLAGS} -o $@
|
||||||
|
@echo
|
||||||
|
@echo "Start with : $(MPIRUN) -np num_proc $(MPIFLAGS) $(PROGRAM)"
|
||||||
|
@echo
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f ${PROGRAM} ${OBJECTS} gmon.out
|
||||||
|
|
||||||
|
clean_all:: clean
|
||||||
|
@rm -f *_ *~ *.bak *.log *.out *.tar *.orig
|
||||||
|
@rm -rf html latex
|
||||||
|
|
||||||
|
run: ${PROGRAM}
|
||||||
|
${MPIRUN} -np 4 ./$^
|
||||||
|
|
||||||
|
# tar the current directory
|
||||||
|
MY_DIR = `basename ${PWD}`
|
||||||
|
tar: clean_all
|
||||||
|
@echo "Tar the directory: " ${MY_DIR}
|
||||||
|
@cd .. ;\
|
||||||
|
tar cf ${MY_DIR}.tar ${MY_DIR} *default.mk ;\
|
||||||
|
cd ${MY_DIR}
|
||||||
|
# tar cf `basename ${PWD}`.tar *
|
||||||
|
|
||||||
|
zip: clean
|
||||||
|
@echo "Zip the directory: " ${MY_DIR}
|
||||||
|
@cd .. ;\
|
||||||
|
zip -r ${MY_DIR}.zip ${MY_DIR} *default.mk ;\
|
||||||
|
cd ${MY_DIR}
|
||||||
|
|
||||||
|
doc:
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) -o $@ $<
|
||||||
|
# 2>&1 | grep -v openmpi
|
||||||
|
|
||||||
|
# special: get rid of compiler warnings genereate by openmpi-files
|
||||||
|
#.cpp.o:
|
||||||
|
# @$(CXX) -c $(CXXFLAGS) $< 2>/tmp/t.txt || grep -sv openmpi /tmp/t.txt
|
||||||
|
# |grep -sv openmpi
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.f.o:
|
||||||
|
$(F77) -c $(FFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
# some tools
|
||||||
|
# Cache behaviour (CXXFLAGS += -g tracks down to source lines; no -pg in linkflags)
|
||||||
|
cache: ${PROGRAM}
|
||||||
|
valgrind --tool=callgrind --simulate-cache=yes ./$^
|
||||||
|
# kcachegrind callgrind.out.<pid> &
|
||||||
|
kcachegrind `ls -1tr callgrind.out.* |tail -1`
|
||||||
|
|
||||||
|
# Check for wrong memory accesses, memory leaks, ...
|
||||||
|
# use smaller data sets
|
||||||
|
# no "-pg" in compile/link options
|
||||||
|
mem: ${PROGRAM}
|
||||||
|
valgrind -v --leak-check=yes --tool=memcheck --undef-value-errors=yes --track-origins=yes --log-file=$^.addr.out --show-reachable=yes mpirun -np 4 ./$^
|
||||||
|
# Graphical interface
|
||||||
|
# valkyrie
|
||||||
|
|
||||||
|
# Simple run time profiling of your code
|
||||||
|
# CXXFLAGS += -g -pg
|
||||||
|
# LINKFLAGS += -pg
|
||||||
|
prof: ${PROGRAM}
|
||||||
|
perf record ./$^
|
||||||
|
perf report
|
||||||
|
# gprof -b ./$^ > gp.out
|
||||||
|
# kprof -f gp.out -p gprof &
|
||||||
|
|
||||||
|
#Trace your heap:
|
||||||
|
#> heaptrack ./main.GCC_
|
||||||
|
#> heaptrack_gui heaptrack.main.GCC_.<pid>.gz
|
||||||
|
heap: ${PROGRAM}
|
||||||
|
heaptrack ./$^ 11
|
||||||
|
heaptrack_gui `ls -1tr heaptrack.$^.* |tail -1` &
|
||||||
|
|
||||||
|
codecheck: $(SOURCES)
|
||||||
|
cppcheck --enable=all --inconclusive --std=c++17 --suppress=missingIncludeSystem $^
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# get the detailed status of all optimization flags
|
||||||
|
info:
|
||||||
|
echo "detailed status of all optimization flags"
|
||||||
|
$(CXX) --version
|
||||||
|
$(CXX) -Q $(CXXFLAGS) --help=optimizers
|
||||||
107
sheet7/ICC_NATIVE_default.mk
Normal file
107
sheet7/ICC_NATIVE_default.mk
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
# Basic Defintions for using INTEL-MPI with its compilers
|
||||||
|
# requires setting of COMPILER=ICC_NATIVE_
|
||||||
|
|
||||||
|
# MPI_ROOT should be defined by shell
|
||||||
|
# path to icpc is contained in $PATH
|
||||||
|
MPI_BIN = $(shell dirname `which icpc` | sed 's/bin\/intel64/mpi\/intel64\/bin/g')/
|
||||||
|
MPI_LIB = $(shell echo ${MPI_BIN} | sed 's/bin/lib/g')
|
||||||
|
|
||||||
|
# Intel-MPI wrappers used gcc as default !!
|
||||||
|
CC = ${MPI_BIN}mpicc -cc=icc
|
||||||
|
CXX = ${MPI_BIN}mpicxx -cxx=icpc
|
||||||
|
F77 = ${MPI_BIN}mpif77 -f77=ifort
|
||||||
|
LINKER = ${CXX}
|
||||||
|
|
||||||
|
MPIRUN = ${MPI_BIN}mpirun
|
||||||
|
|
||||||
|
WARNINGS = -Wall -Wextra -pedantic -Woverloaded-virtual -Wfloat-equal -Wshadow
|
||||||
|
# -Weffc++ -Wunreachable-code -Winline
|
||||||
|
CXXFLAGS += -O3 -fargument-noalias -DNDEBUG -std=c++17 ${WARNINGS} ${MPI_COMPILE_FLAGS}
|
||||||
|
CFLAGS += -O3 -fargument-noalias -DNDEBUG -Wall -Wextra -pedantic -Wfloat-equal \
|
||||||
|
-Wshadow ${MPI_COMPILE_FLAGS}
|
||||||
|
# -vec-report=3 -mkl
|
||||||
|
# -guide -parallel
|
||||||
|
# -guide-opts=string -guide-par[=n] -guide-vec[=n]
|
||||||
|
# -auto-p32 -simd
|
||||||
|
|
||||||
|
# use MKL by INTEL
|
||||||
|
LINKFLAGS += -mkl ${MPI_LINK_FLAGS}
|
||||||
|
|
||||||
|
default: ${PROGRAM}
|
||||||
|
|
||||||
|
${PROGRAM}: ${OBJECTS}
|
||||||
|
$(LINKER) $^ ${LINKFLAGS} -o $@
|
||||||
|
@echo
|
||||||
|
@echo "Start with : $(MPIRUN) -np num_proc $(MPIFLAGS) $(PROGRAM)"
|
||||||
|
@echo
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${PROGRAM} ${OBJECTS}
|
||||||
|
|
||||||
|
clean_all:: clean
|
||||||
|
@rm -f *_ *~ *.bak *.log *.out *.tar
|
||||||
|
|
||||||
|
run: ${PROGRAM}
|
||||||
|
(export LD_LIBRARY_PATH=${MPI_LIB}:${LD_LIBRARY_PATH} ;${MPIRUN} -np 4 ./$^ ${PROG_ARGS})
|
||||||
|
|
||||||
|
# tar the current directory
|
||||||
|
MY_DIR = `basename ${PWD}`
|
||||||
|
tar: clean_all
|
||||||
|
@echo "Tar the directory: " ${MY_DIR}
|
||||||
|
@cd .. ;\
|
||||||
|
tar cf ${MY_DIR}.tar ${MY_DIR} *default.mk ;\
|
||||||
|
cd ${MY_DIR}
|
||||||
|
# tar cf `basename ${PWD}`.tar *
|
||||||
|
|
||||||
|
doc:
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.f.o:
|
||||||
|
$(F77) -c $(FFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
# # some tools
|
||||||
|
# # Cache behaviour (CXXFLAGS += -g tracks down to source lines)
|
||||||
|
# cache: ${PROGRAM}
|
||||||
|
# valgrind --tool=callgrind --simulate-cache=yes ./$^
|
||||||
|
# # kcachegrind callgrind.out.<pid> &
|
||||||
|
#
|
||||||
|
# # Check for wrong memory accesses, memory leaks, ...
|
||||||
|
# # use smaller data sets
|
||||||
|
# mem: ${PROGRAM}
|
||||||
|
# valgrind -v --leak-check=yes --tool=memcheck --undef-value-errors=yes --track-origins=yes --log-file=$^.addr.out --show-reachable=yes ./$^
|
||||||
|
#
|
||||||
|
# # Simple run time profiling of your code
|
||||||
|
# # CXXFLAGS += -g -pg
|
||||||
|
# # LINKFLAGS += -pg
|
||||||
|
# prof: ${PROGRAM}
|
||||||
|
# ./$^
|
||||||
|
# gprof -b ./$^ > gp.out
|
||||||
|
# # kprof -f gp.out -p gprof &
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
mem: inspector
|
||||||
|
prof: amplifier
|
||||||
|
cache: amplifier
|
||||||
|
|
||||||
|
gap_par_report:
|
||||||
|
${CXX} -c -guide -parallel $(SOURCES) 2> gap.txt
|
||||||
|
|
||||||
|
# GUI for performance report
|
||||||
|
amplifier: ${PROGRAM}
|
||||||
|
${BINDIR}../vtune_amplifier_xe_2013/bin64/amplxe-gui &
|
||||||
|
|
||||||
|
# GUI for Memory and Thread analyzer (race condition)
|
||||||
|
inspector: ${PROGRAM}
|
||||||
|
# http://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process
|
||||||
|
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
|
||||||
|
${BINDIR}../inspector_xe_2013/bin64/inspxe-gui &
|
||||||
112
sheet7/ICC_default.mk
Normal file
112
sheet7/ICC_default.mk
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
# Basic Defintions for using INTEL compilers with OpenMPI headers and libraries
|
||||||
|
# requires setting of COMPILER=ICC_
|
||||||
|
|
||||||
|
# MPI_ROOT should be defined by shell
|
||||||
|
MPI_ROOT=/usr
|
||||||
|
|
||||||
|
CC = icc
|
||||||
|
CXX = icpc
|
||||||
|
F77 = ifort
|
||||||
|
LINKER = ${CXX}
|
||||||
|
|
||||||
|
MPIRUN = ${MPI_ROOT}/bin/mpirun
|
||||||
|
|
||||||
|
# no differences when C or C++ is used !! (always used options from mpicxx)
|
||||||
|
MPI_COMPILE_FLAGS = `${MPI_ROOT}/bin/mpicxx -showme:compile`
|
||||||
|
MPI_LINK_FLAGS = `${MPI_ROOT}/bin/mpicxx -showme:link`
|
||||||
|
# MPI_LINK_FLAGS = -pthread -L/usr/lib/openmpi/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl
|
||||||
|
|
||||||
|
|
||||||
|
WARNINGS = -Wall -Wextra -pedantic -Woverloaded-virtual -Wfloat-equal -Wshadow
|
||||||
|
# -Weffc++ -Wunreachable-code -Winline
|
||||||
|
CXXFLAGS += -O3 -std=c++17 -fargument-noalias -DNDEBUG ${WARNINGS} ${MPI_COMPILE_FLAGS}
|
||||||
|
CFLAGS += -O3 -fargument-noalias -DNDEBUG -Wall -Wextra -pedantic -Wfloat-equal \
|
||||||
|
-Wshadow ${MPI_COMPILE_FLAGS}
|
||||||
|
# -vec-report=3 -mkl
|
||||||
|
# -guide -parallel
|
||||||
|
# -guide-opts=string -guide-par[=n] -guide-vec[=n]
|
||||||
|
# -auto-p32 -simd
|
||||||
|
|
||||||
|
# use MKL by INTEL
|
||||||
|
LINKFLAGS += -mkl
|
||||||
|
# use MPI by Compiler
|
||||||
|
LINKFLAGS += ${MPI_LINK_FLAGS}
|
||||||
|
|
||||||
|
default: ${PROGRAM}
|
||||||
|
|
||||||
|
${PROGRAM}: ${OBJECTS}
|
||||||
|
$(LINKER) $^ ${LINKFLAGS} -o $@
|
||||||
|
@echo
|
||||||
|
@echo "Start with : $(MPIRUN) -np num_proc $(MPIFLAGS) $(PROGRAM)"
|
||||||
|
@echo
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${PROGRAM} ${OBJECTS}
|
||||||
|
|
||||||
|
clean_all:: clean
|
||||||
|
@rm -f *_ *~ *.bak *.log *.out *.tar
|
||||||
|
|
||||||
|
run: ${PROGRAM}
|
||||||
|
${MPIRUN} -np 4 ./$^
|
||||||
|
|
||||||
|
# tar the current directory
|
||||||
|
MY_DIR = `basename ${PWD}`
|
||||||
|
tar: clean_all
|
||||||
|
@echo "Tar the directory: " ${MY_DIR}
|
||||||
|
@cd .. ;\
|
||||||
|
tar cf ${MY_DIR}.tar ${MY_DIR} *default.mk ;\
|
||||||
|
cd ${MY_DIR}
|
||||||
|
# tar cf `basename ${PWD}`.tar *
|
||||||
|
|
||||||
|
doc:
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.f.o:
|
||||||
|
$(F77) -c $(FFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
# # some tools
|
||||||
|
# # Cache behaviour (CXXFLAGS += -g tracks down to source lines)
|
||||||
|
# cache: ${PROGRAM}
|
||||||
|
# valgrind --tool=callgrind --simulate-cache=yes ./$^
|
||||||
|
# # kcachegrind callgrind.out.<pid> &
|
||||||
|
#
|
||||||
|
# # Check for wrong memory accesses, memory leaks, ...
|
||||||
|
# # use smaller data sets
|
||||||
|
# mem: ${PROGRAM}
|
||||||
|
# valgrind -v --leak-check=yes --tool=memcheck --undef-value-errors=yes --track-origins=yes --log-file=$^.addr.out --show-reachable=yes ./$^
|
||||||
|
#
|
||||||
|
# # Simple run time profiling of your code
|
||||||
|
# # CXXFLAGS += -g -pg
|
||||||
|
# # LINKFLAGS += -pg
|
||||||
|
# prof: ${PROGRAM}
|
||||||
|
# ./$^
|
||||||
|
# gprof -b ./$^ > gp.out
|
||||||
|
# # kprof -f gp.out -p gprof &
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
mem: inspector
|
||||||
|
prof: amplifier
|
||||||
|
cache: amplifier
|
||||||
|
|
||||||
|
gap_par_report:
|
||||||
|
${CXX} -c -guide -parallel $(SOURCES) 2> gap.txt
|
||||||
|
|
||||||
|
# GUI for performance report
|
||||||
|
amplifier: ${PROGRAM}
|
||||||
|
${BINDIR}../vtune_amplifier_xe_2013/bin64/amplxe-gui &
|
||||||
|
|
||||||
|
# GUI for Memory and Thread analyzer (race condition)
|
||||||
|
inspector: ${PROGRAM}
|
||||||
|
# http://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process
|
||||||
|
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
|
||||||
|
${BINDIR}../inspector_xe_2013/bin64/inspxe-gui &
|
||||||
128
sheet7/OPENMPI_CLANG_default.mk
Normal file
128
sheet7/OPENMPI_CLANG_default.mk
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
# Basic Defintions for using OpenMPI with CLANG compilers
|
||||||
|
# requires setting of COMPILER=OPENMPI_CLANG_
|
||||||
|
|
||||||
|
# Pass CLANG Compilers to the OpenMPI wrappers
|
||||||
|
# see: https://www.open-mpi.org/faq/?category=mpi-apps#override-wrappers-after-v1.0
|
||||||
|
EXPORT = export OMPI_CXX=clang++; export OMPI_CC=clang; export OMPI_mpifort=flang
|
||||||
|
|
||||||
|
CC = mpicc
|
||||||
|
CXX = mpicxx
|
||||||
|
F77 = mpifort
|
||||||
|
LINKER = ${CXX}
|
||||||
|
|
||||||
|
MPIRUN = ${MPI_BIN}mpirun
|
||||||
|
|
||||||
|
#http://clang.llvm.org/docs/UsersManual.html#options-to-control-error-and-warning-messages
|
||||||
|
SILENCE_MPI = -Wno-weak-vtables -Wno-old-style-cast -Wno-cast-align -Wno-deprecated
|
||||||
|
SILENCE_MPI+= -Wno-sign-conversion -Wno-reserved-id-macro -Wno-c++98-compat-pedantic
|
||||||
|
SILENCE_MPI+= -Wno-zero-as-null-pointer-constant -Wno-source-uses-openmp
|
||||||
|
WARNINGS = -Weverything -Wno-c++98-compat -Wno-weak-vtables -ferror-limit=3 ${SILENCE_MPI}
|
||||||
|
#-fsyntax-only -Wdocumentation -Wconversion -Wshadow -Wfloat-conversion -pedantic
|
||||||
|
CXXFLAGS += -Ofast -std=c++17 ${WARNINGS}
|
||||||
|
#CXXFLAGS += -Ofast -std=c++17
|
||||||
|
# -ftrapv
|
||||||
|
#
|
||||||
|
CFLAGS += -Ofast -Weverything -ferror-limit=3 ${MPI_COMPILE_FLAGS}
|
||||||
|
|
||||||
|
# OpenMP
|
||||||
|
#CXXFLAGS += -fopenmp
|
||||||
|
#LINKFLAGS += -fopenmp
|
||||||
|
|
||||||
|
# tidy_check
|
||||||
|
SWITCH_OFF=,-readability-magic-numbers,-readability-redundant-control-flow,-readability-redundant-member-init
|
||||||
|
SWITCH_OFF+=,-readability-redundant-member-init,-readability-isolate-declaration
|
||||||
|
#READABILITY=,readability*${SWITCH_OFF}
|
||||||
|
#TIDYFLAGS = -checks=llvm-*,-llvm-header-guard -header-filter=.* -enable-check-profile -extra-arg="-std=c++17" -extra-arg="-fopenmp"
|
||||||
|
TIDYFLAGS = -checks=llvm-*,-llvm-header-guard${READABILITY} -header-filter=.* -enable-check-profile -extra-arg="-std=c++17" -extra-arg="-fopenmp"
|
||||||
|
#TIDYFLAGS += -checks='modernize*
|
||||||
|
|
||||||
|
MPI_COMPILE_FLAGS = `${MPI_BIN}mpicxx -showme:compile`
|
||||||
|
MPI_LINK_FLAGS = `${MPI_BIN}mpicxx -showme:link`
|
||||||
|
#TIDYFLAGS += ${MPI_COMPILE_FLAGS}
|
||||||
|
TIDYFLAGS += -extra-arg="-I/usr/lib/x86_64-linux-gnu/openmpi/include"
|
||||||
|
#check:
|
||||||
|
# echo ${MPI_COMPILE_FLAGS}
|
||||||
|
|
||||||
|
default: ${PROGRAM}
|
||||||
|
|
||||||
|
${PROGRAM}: ${OBJECTS}
|
||||||
|
@( ${EXPORT}; $(LINKER) $^ ${LINKFLAGS} -o $@ )
|
||||||
|
@echo
|
||||||
|
@echo "Start with : $(MPIRUN) -np num_proc $(MPIFLAGS) $(PROGRAM)"
|
||||||
|
@echo
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${PROGRAM} ${OBJECTS}
|
||||||
|
|
||||||
|
clean_all:: clean
|
||||||
|
@rm -f *_ *~ *.bak *.log *.out *.tar
|
||||||
|
|
||||||
|
codecheck: tidy_check
|
||||||
|
tidy_check:
|
||||||
|
clang-tidy ${SOURCES} ${TIDYFLAGS} -- ${SOURCES}
|
||||||
|
# see also http://clang-developers.42468.n3.nabble.com/Error-while-trying-to-load-a-compilation-database-td4049722.html
|
||||||
|
|
||||||
|
run: ${PROGRAM}
|
||||||
|
${MPIRUN} -np 4 ./$^ ${PROG_ARGS}
|
||||||
|
|
||||||
|
# tar the current directory
|
||||||
|
MY_DIR = `basename ${PWD}`
|
||||||
|
tar: clean_all
|
||||||
|
@echo "Tar the directory: " ${MY_DIR}
|
||||||
|
@cd .. ;\
|
||||||
|
tar cf ${MY_DIR}.tar ${MY_DIR} *default.mk ;\
|
||||||
|
cd ${MY_DIR}
|
||||||
|
# tar cf `basename ${PWD}`.tar *
|
||||||
|
|
||||||
|
doc:
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
@( ${EXPORT}; $(CXX) -c $(CXXFLAGS) -o $@ $< )
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@( ${EXPORT}; $(CC) -c $(CFLAGS) -o $@ $< )
|
||||||
|
|
||||||
|
.f.o:
|
||||||
|
$(F77) -c $(FFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
# # some tools
|
||||||
|
# # Cache behaviour (CXXFLAGS += -g tracks down to source lines)
|
||||||
|
# cache: ${PROGRAM}
|
||||||
|
# valgrind --tool=callgrind --simulate-cache=yes ./$^
|
||||||
|
# # kcachegrind callgrind.out.<pid> &
|
||||||
|
#
|
||||||
|
# # Check for wrong memory accesses, memory leaks, ...
|
||||||
|
# # use smaller data sets
|
||||||
|
# mem: ${PROGRAM}
|
||||||
|
# valgrind -v --leak-check=yes --tool=memcheck --undef-value-errors=yes --track-origins=yes --log-file=$^.addr.out --show-reachable=yes ./$^
|
||||||
|
#
|
||||||
|
# # Simple run time profiling of your code
|
||||||
|
# # CXXFLAGS += -g -pg
|
||||||
|
# # LINKFLAGS += -pg
|
||||||
|
# prof: ${PROGRAM}
|
||||||
|
# ./$^
|
||||||
|
# gprof -b ./$^ > gp.out
|
||||||
|
# # kprof -f gp.out -p gprof &
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
mem: inspector
|
||||||
|
prof: amplifier
|
||||||
|
cache: amplifier
|
||||||
|
|
||||||
|
gap_par_report:
|
||||||
|
${CXX} -c -guide -parallel $(SOURCES) 2> gap.txt
|
||||||
|
|
||||||
|
# GUI for performance report
|
||||||
|
amplifier: ${PROGRAM}
|
||||||
|
${BINDIR}../vtune_amplifier_xe_2013/bin64/amplxe-gui &
|
||||||
|
|
||||||
|
# GUI for Memory and Thread analyzer (race condition)
|
||||||
|
inspector: ${PROGRAM}
|
||||||
|
# http://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process
|
||||||
|
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
|
||||||
|
${BINDIR}../inspector_xe_2013/bin64/inspxe-gui &
|
||||||
107
sheet7/OPENMPI_ICC_default.mk
Normal file
107
sheet7/OPENMPI_ICC_default.mk
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
# Basic Defintions for using OpenMPI with Intel compilers
|
||||||
|
# requires setting of COMPILER=OPENMPI_ICC_
|
||||||
|
|
||||||
|
# Pass Intel Compilers to the OpenMPI wrappers
|
||||||
|
# see: https://www.open-mpi.org/faq/?category=mpi-apps#override-wrappers-after-v1.0
|
||||||
|
EXPORT = export OMPI_CXX=icpc; export OMPI_CC=icc; export OMPI_mpifort=ifort
|
||||||
|
|
||||||
|
CC = mpicc
|
||||||
|
CXX = mpicxx
|
||||||
|
F77 = mpifort
|
||||||
|
LINKER = ${CXX}
|
||||||
|
|
||||||
|
MPIRUN = ${MPI_BIN}mpirun
|
||||||
|
|
||||||
|
WARNINGS = -Wall -Wextra -pedantic -Woverloaded-virtual -Wfloat-equal -Wshadow
|
||||||
|
# -Weffc++ -Wunreachable-code -Winline
|
||||||
|
CXXFLAGS += -fast -fargument-noalias -DNDEBUG -std=c++17 ${WARNINGS}
|
||||||
|
CFLAGS += -O3 -fargument-noalias -DNDEBUG -Wall -Wextra -pedantic -Wfloat-equal -Wshadow
|
||||||
|
# -vec-report=3 -mkl
|
||||||
|
# -guide -parallel
|
||||||
|
# -guide-opts=string -guide-par[=n] -guide-vec[=n]
|
||||||
|
# -auto-p32 -simd
|
||||||
|
|
||||||
|
# use MKL by INTEL
|
||||||
|
LINKFLAGS += -O3 -mkl ${MPI_LINK_FLAGS}
|
||||||
|
# ipo: warning #11021: unresolved __GI_memset
|
||||||
|
# see: https://software.intel.com/en-us/articles/ipo-warning-11021-unresolved-symbols-referenced-a-dynamic-library
|
||||||
|
LINKFLAGS +=
|
||||||
|
|
||||||
|
default: ${PROGRAM}
|
||||||
|
|
||||||
|
${PROGRAM}: ${OBJECTS}
|
||||||
|
@( ${EXPORT}; $(LINKER) $^ ${LINKFLAGS} -o $@ )
|
||||||
|
@echo
|
||||||
|
@echo "Start with : $(MPIRUN) -np num_proc $(MPIFLAGS) $(PROGRAM)"
|
||||||
|
@echo
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${PROGRAM} ${OBJECTS}
|
||||||
|
|
||||||
|
clean_all:: clean
|
||||||
|
@rm -f *_ *~ *.bak *.log *.out *.tar
|
||||||
|
|
||||||
|
run: ${PROGRAM}
|
||||||
|
${MPIRUN} -np 4 ./$^ ${PROG_ARGS}
|
||||||
|
|
||||||
|
# tar the current directory
|
||||||
|
MY_DIR = `basename ${PWD}`
|
||||||
|
tar: clean_all
|
||||||
|
@echo "Tar the directory: " ${MY_DIR}
|
||||||
|
@cd .. ;\
|
||||||
|
tar cf ${MY_DIR}.tar ${MY_DIR} *default.mk ;\
|
||||||
|
cd ${MY_DIR}
|
||||||
|
# tar cf `basename ${PWD}`.tar *
|
||||||
|
|
||||||
|
doc:
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
@( ${EXPORT}; $(CXX) -c $(CXXFLAGS) -o $@ $< )
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@( ${EXPORT}; $(CC) -c $(CFLAGS) -o $@ $< )
|
||||||
|
|
||||||
|
.f.o:
|
||||||
|
$(F77) -c $(FFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
# # some tools
|
||||||
|
# # Cache behaviour (CXXFLAGS += -g tracks down to source lines)
|
||||||
|
# cache: ${PROGRAM}
|
||||||
|
# valgrind --tool=callgrind --simulate-cache=yes ./$^
|
||||||
|
# # kcachegrind callgrind.out.<pid> &
|
||||||
|
#
|
||||||
|
# # Check for wrong memory accesses, memory leaks, ...
|
||||||
|
# # use smaller data sets
|
||||||
|
# mem: ${PROGRAM}
|
||||||
|
# valgrind -v --leak-check=yes --tool=memcheck --undef-value-errors=yes --track-origins=yes --log-file=$^.addr.out --show-reachable=yes ./$^
|
||||||
|
#
|
||||||
|
# # Simple run time profiling of your code
|
||||||
|
# # CXXFLAGS += -g -pg
|
||||||
|
# # LINKFLAGS += -pg
|
||||||
|
# prof: ${PROGRAM}
|
||||||
|
# ./$^
|
||||||
|
# gprof -b ./$^ > gp.out
|
||||||
|
# # kprof -f gp.out -p gprof &
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
mem: inspector
|
||||||
|
prof: amplifier
|
||||||
|
cache: amplifier
|
||||||
|
|
||||||
|
gap_par_report:
|
||||||
|
${CXX} -c -guide -parallel $(SOURCES) 2> gap.txt
|
||||||
|
|
||||||
|
# GUI for performance report
|
||||||
|
amplifier: ${PROGRAM}
|
||||||
|
${BINDIR}../vtune_amplifier_xe_2013/bin64/amplxe-gui &
|
||||||
|
|
||||||
|
# GUI for Memory and Thread analyzer (race condition)
|
||||||
|
inspector: ${PROGRAM}
|
||||||
|
# http://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process
|
||||||
|
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
|
||||||
|
${BINDIR}../inspector_xe_2013/bin64/inspxe-gui &
|
||||||
125
sheet7/PGI_NATIVE_default.mk
Normal file
125
sheet7/PGI_NATIVE_default.mk
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
# Use the MPI-wrappers from the PGI compiler suite.
|
||||||
|
# requires setting of COMPILER=PGI_MPI_
|
||||||
|
#
|
||||||
|
# requires
|
||||||
|
# sudo apt install librdmacm1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Details for run time information
|
||||||
|
# export PGI_ACC_TIME=1
|
||||||
|
# unset PGI_ACC_TIME
|
||||||
|
# export PGI_ACC_NOTIFY=1
|
||||||
|
# export PGI_ACC_NOTIFY=3
|
||||||
|
# unset PGI_ACC_NOTIFY
|
||||||
|
|
||||||
|
|
||||||
|
PGI_PATH = /opt/pgi/linux86-64/2019/bin
|
||||||
|
#ifeq "$(HOSTNAME)" "mephisto.uni-graz.at"
|
||||||
|
# # mephisto
|
||||||
|
# PGI_PATH = /share/apps/pgi/linux86-64/2016/bin
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#MPI_ROOT=${PGI_PATH}mpi/mpich/bin/
|
||||||
|
MPI_ROOT= ${PGI_PATH}/../mpi/openmpi-3.1.3/bin/
|
||||||
|
MPIRUN = ${MPI_ROOT}mpirun
|
||||||
|
|
||||||
|
CC = ${MPI_ROOT}mpicc
|
||||||
|
CXX = ${MPI_ROOT}mpicxx
|
||||||
|
#F77 = ${MPI_ROOT}mpif77
|
||||||
|
ifndef LINKER
|
||||||
|
LINKER = ${CC}
|
||||||
|
endif
|
||||||
|
LINKER = ${CXX}
|
||||||
|
|
||||||
|
WARNINGS = -Minform=warn
|
||||||
|
|
||||||
|
PGI_PROFILING += -Minfo=loop,vect,opt,intensity,mp,accel
|
||||||
|
#PGI_PROFILING += -Mprof=lines –Minfo=ccff
|
||||||
|
|
||||||
|
CXXFLAGS += -e3 -std=c++17 -fast ${PGI_PROFILING} ${WARNINGS} -Mnodepchk
|
||||||
|
CFLAGS += -fast ${PGI_PROFILING} ${WARNINGS} -Mnodepchk
|
||||||
|
#
|
||||||
|
# for OpenACC
|
||||||
|
# Target architecture (nvidia,host)
|
||||||
|
TA_ARCH = host
|
||||||
|
#TA_ARCH = nvidia,host
|
||||||
|
#TA_ARCH = -ta=nvidia:cc2+,cuda5.5,fastmath
|
||||||
|
#TA_ARCH = -acc -DNDEBUG -ta=nvidia:cc2+,cuda5.5,fastmath,keepgpu
|
||||||
|
#TA_ARCH = -acc -DNDEBUG -ta=nvidia:cc2+,fastmath,keepgpu
|
||||||
|
|
||||||
|
#,keepgpu
|
||||||
|
# CFLAGS = -O3 -ta=$(TA_ARCH)
|
||||||
|
#CFLAGS += -B -gopt $(TA_ARCH)
|
||||||
|
#CXXFLAGS += -B -gopt $(TA_ARCH)
|
||||||
|
# -Minfo=all
|
||||||
|
|
||||||
|
# libcudart.a is needed for direct CUDA calls
|
||||||
|
#LINKFLAGS = -gopt $(TA_ARCH) -L${BINDIR}../lib $(PGI_PROFILING)
|
||||||
|
# -lcudart
|
||||||
|
|
||||||
|
default: ${PROGRAM}
|
||||||
|
|
||||||
|
${PROGRAM}: ${OBJECTS}
|
||||||
|
$(LINKER) $^ ${LINKFLAGS} -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${PROGRAM} ${OBJECTS} *.gpu *gprof.out
|
||||||
|
|
||||||
|
clean_all:: clean
|
||||||
|
@rm -f *_ *~ *.bak *.log *.out *.tar
|
||||||
|
|
||||||
|
#run: clean ${PROGRAM}
|
||||||
|
run: ${PROGRAM}
|
||||||
|
${MPIRUN} -np 4 ${OPTIRUN} ./${PROGRAM}
|
||||||
|
|
||||||
|
# tar the current directory
|
||||||
|
MY_DIR = `basename ${PWD}`
|
||||||
|
tar: clean_all
|
||||||
|
@echo "Tar the directory: " ${MY_DIR}
|
||||||
|
@cd .. ;\
|
||||||
|
tar cf ${MY_DIR}.tar ${MY_DIR} *default.mk ;\
|
||||||
|
cd ${MY_DIR}
|
||||||
|
# tar cf `basename ${PWD}`.tar *
|
||||||
|
|
||||||
|
doc:
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) -c $(CXXFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.f.o:
|
||||||
|
$(F77) -c $(FFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
# # some tools
|
||||||
|
# # Simple run time profiling of your code
|
||||||
|
# # CXXFLAGS += -g -pg
|
||||||
|
# # LINKFLAGS += -pg
|
||||||
|
|
||||||
|
|
||||||
|
# Profiling options PGI, see: pgcollect -help
|
||||||
|
CPU_PROF = -allcache
|
||||||
|
GPU_PROF = -cuda=gmem,branch,cc13 -cudainit
|
||||||
|
#GPU_PROF = -cuda=branch:cc20
|
||||||
|
#
|
||||||
|
PROF_FILE = pgprof.out
|
||||||
|
|
||||||
|
prof: ${PROGRAM}
|
||||||
|
# ./$^
|
||||||
|
# $(CUDA_HOME)/bin/nvvp &
|
||||||
|
# export LD_LIBRARY_PATH=/state/partition1/apps/pgi/linux86-64/12.9/lib:$LD_LIBRARY_PATH
|
||||||
|
${OPTIRUN} ${BINDIR}pgcollect $(GPU_PROF) ./$^
|
||||||
|
${OPTIRUN} ${BINDIR}pgprof -exe ./$^ $(PROF_FILE) &
|
||||||
|
|
||||||
|
|
||||||
|
# Memory checker (slooooow!!!):
|
||||||
|
# see doc at /usr/local/cuda/doc/cuda-memcheck.pdf
|
||||||
|
# mem: ${PROGRAM}
|
||||||
|
# $(CUDA_HOME)memcheck ./$^
|
||||||
2877
sheet7/jacobi.template/Doxyfile
Normal file
2877
sheet7/jacobi.template/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
56
sheet7/jacobi.template/Makefile
Normal file
56
sheet7/jacobi.template/Makefile
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# COMPILER=GCC_SEQ_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
MAIN = main
|
||||||
|
SOURCES = ${MAIN}.cpp vdop.cpp geom.cpp par_geom.cpp\
|
||||||
|
getmatrix.cpp jacsolve.cpp userset.cpp
|
||||||
|
# cuthill_mckee_ordering.cpp
|
||||||
|
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = ${MAIN}.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
# -DNDEBUG
|
||||||
|
# -pg slows down the code on my laptop when using CLANG_
|
||||||
|
LINKFLAGS += -g
|
||||||
|
#-pg
|
||||||
|
#CXXFLAGS += -Q --help=optimizers
|
||||||
|
#CXXFLAGS += -fopt-info
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# additional specific cleaning in this directory
|
||||||
|
clean_all::
|
||||||
|
@rm -f t.dat*
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# special testing
|
||||||
|
# NPROCS = 4
|
||||||
|
#
|
||||||
|
TFILE = t.dat
|
||||||
|
# TTMP = t.tmp
|
||||||
|
#
|
||||||
|
graph: $(PROGRAM)
|
||||||
|
# @rm -f $(TFILE).*
|
||||||
|
# next two lines only sequentially
|
||||||
|
./$(PROGRAM)
|
||||||
|
@mv $(TFILE).000 $(TFILE)
|
||||||
|
# $(MPIRUN) $(MPIFLAGS) -np $(NPROCS) $(PROGRAM)
|
||||||
|
# @echo " "; echo "Manipulate data for graphics."; echo " "
|
||||||
|
# @cat $(TFILE).* > $(TTMP)
|
||||||
|
# @sort -b -k 2 $(TTMP) -o $(TTMP).1
|
||||||
|
# @sort -b -k 1 $(TTMP).1 -o $(TTMP).2
|
||||||
|
# @awk -f nl.awk $(TTMP).2 > $(TFILE)
|
||||||
|
# @rm -f $(TTMP).* $(TTMP) $(TFILE).*
|
||||||
|
#
|
||||||
|
-gnuplot jac.dem
|
||||||
43
sheet7/jacobi.template/ascii_read_meshvector.m
Normal file
43
sheet7/jacobi.template/ascii_read_meshvector.m
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
function [ xc, ia, v ] = ascii_read_meshvector( fname )
|
||||||
|
%
|
||||||
|
% Loads the 2D triangular mesh (coordinates, vertex connectivity)
|
||||||
|
% together with values on its vertices from an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The input file format is compatible
|
||||||
|
% with Mesh_2d_3_matlab:Write_ascii_matlab(..) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% IN: fname - filename
|
||||||
|
% OUT: xc - coordinates
|
||||||
|
% ia - mesh connectivity
|
||||||
|
% v - solution vector
|
||||||
|
|
||||||
|
DELIMETER = ' ';
|
||||||
|
|
||||||
|
fprintf('Read file %s\n',fname)
|
||||||
|
|
||||||
|
% Read mesh constants
|
||||||
|
nn = dlmread(fname,DELIMETER,[0 0 0 3]); %% row_1, col_1, row_2, col_2 in C indexing!!!
|
||||||
|
nnode = nn(1);
|
||||||
|
ndim = nn(2);
|
||||||
|
nelem = nn(3);
|
||||||
|
nvert = nn(4);
|
||||||
|
|
||||||
|
% Read coordinates
|
||||||
|
row_start = 0+1;
|
||||||
|
row_end = 0+nnode;
|
||||||
|
xc = dlmread(fname,DELIMETER,[row_start 0 row_end ndim-1]);
|
||||||
|
|
||||||
|
% Read connectivity
|
||||||
|
row_start = row_end+1;
|
||||||
|
row_end = row_end+nelem;
|
||||||
|
ia = dlmread(fname,DELIMETER,[row_start 0 row_end nvert-1]);
|
||||||
|
|
||||||
|
% Read solution
|
||||||
|
row_start = row_end+1;
|
||||||
|
row_end = row_end+nnode;
|
||||||
|
v = dlmread(fname,DELIMETER,[row_start 0 row_end 0]);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
54
sheet7/jacobi.template/ascii_write_mesh.m
Normal file
54
sheet7/jacobi.template/ascii_write_mesh.m
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
function ascii_write_mesh( xc, ia, e, basename)
|
||||||
|
%
|
||||||
|
% Saves the 2D triangular mesh in the minimal way (only coordinates, vertex connectivity, minimal boundary edge info)
|
||||||
|
% in an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The output file format is compatible with Mesh_2d_3_matlab:Mesh_2d_3_matlab(std::string const &fname) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
% IN:
|
||||||
|
% coordinates xc: [2][nnode]
|
||||||
|
% connectivity ia: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
% basename: file name without extension
|
||||||
|
%
|
||||||
|
% Data have been generated via <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>.
|
||||||
|
%
|
||||||
|
fname = [basename, '.txt'];
|
||||||
|
|
||||||
|
nnode = int32(size(xc,2));
|
||||||
|
ndim = int32(size(xc,1));
|
||||||
|
nelem = int32(size(ia,2));
|
||||||
|
nvert_e = int32(3);
|
||||||
|
|
||||||
|
|
||||||
|
dlmwrite(fname,nnode,'delimiter','\t','precision',16) % number of nodes
|
||||||
|
dlmwrite(fname,ndim,'-append','delimiter','\t','precision',16) % space dimension
|
||||||
|
dlmwrite(fname,nelem,'-append','delimiter','\t','precision',16) % number of elements
|
||||||
|
dlmwrite(fname,nvert_e,'-append','delimiter','\t','precision',16) % number of vertices per element
|
||||||
|
|
||||||
|
%% dlmwrite(fname,xc(:),'-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
dlmwrite(fname,xc([1,2],:).','-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
|
||||||
|
%% no subdomain info transferred
|
||||||
|
tmp=int32(ia(1:3,:));
|
||||||
|
% dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
|
||||||
|
%% store only start and end point of boundary edges,
|
||||||
|
nbedges = size(e,2);
|
||||||
|
dlmwrite(fname,nbedges,'-append','delimiter','\t','precision',16) % number boundary edges
|
||||||
|
tmp=int32(e(1:2,:));
|
||||||
|
% dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
|
||||||
|
%% Add subdomain information to edges
|
||||||
|
tmp=int32(e(6:7,:));
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % subdomain information to edges
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
51
sheet7/jacobi.template/ascii_write_subdomains.m
Normal file
51
sheet7/jacobi.template/ascii_write_subdomains.m
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
function ascii_write_subdomains( xc, ia, e, basename)
|
||||||
|
%
|
||||||
|
% Saves the 2D triangular mesh in the minimal way (only coordinates, vertex connectivity, minimal boundary edge info)
|
||||||
|
% in an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The output file format is compatible with Mesh_2d_3_matlab:Mesh_2d_3_matlab(std::string const &fname) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
% IN:
|
||||||
|
% coordinates xc: [2][nnode]
|
||||||
|
% connectivity ia: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
% basename: file name without extension
|
||||||
|
%
|
||||||
|
% Data have been generated via <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>.
|
||||||
|
%
|
||||||
|
fname = [basename, '_sd.txt'];
|
||||||
|
|
||||||
|
nnode = int32(size(xc,2));
|
||||||
|
ndim = int32(size(xc,1));
|
||||||
|
nelem = int32(size(ia,2))
|
||||||
|
nvert_e = int32(3);
|
||||||
|
|
||||||
|
|
||||||
|
% dlmwrite(fname,nnode,'delimiter','\t','precision',16) % number of nodes
|
||||||
|
% dlmwrite(fname,ndim,'-append','delimiter','\t','precision',16) % space dimension
|
||||||
|
% dlmwrite(fname,nelem,'-append','delimiter','\t','precision',16) % number of elements
|
||||||
|
dlmwrite(fname,nelem,'delimiter','\t','precision',16) % number of elements
|
||||||
|
% dlmwrite(fname,nvert_e,'-append','delimiter','\t','precision',16) % number of vertices per element
|
||||||
|
|
||||||
|
% % dlmwrite(fname,xc(:),'-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
% dlmwrite(fname,xc([1,2],:).','-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
|
||||||
|
% subdomain info
|
||||||
|
tmp=int32(ia(4,:));
|
||||||
|
% % dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
% dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t') % connectivity in Matlab indexing
|
||||||
|
|
||||||
|
% % store only start and end point of boundary edges,
|
||||||
|
% nbedges = size(e,2);
|
||||||
|
% dlmwrite(fname,nbedges,'-append','delimiter','\t','precision',16) % number boundary edges
|
||||||
|
% tmp=int32(e(1:2,:));
|
||||||
|
% % dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
% dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
|
||||||
|
end
|
||||||
218
sheet7/jacobi.template/cuthill_mckee_ordering.cpp
Normal file
218
sheet7/jacobi.template/cuthill_mckee_ordering.cpp
Normal file
|
|
@ -0,0 +1,218 @@
|
||||||
|
//=======================================================================
|
||||||
|
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||||
|
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||||
|
//
|
||||||
|
// This file is part of the Boost Graph Library
|
||||||
|
//
|
||||||
|
// You should have received a copy of the License Agreement for the
|
||||||
|
// Boost Graph Library along with the software; see the file LICENSE.
|
||||||
|
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||||
|
// Dame, IN 46556.
|
||||||
|
//
|
||||||
|
// Permission to modify the code and to distribute modified code is
|
||||||
|
// granted, provided the text of this NOTICE is retained, a notice that
|
||||||
|
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||||
|
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||||
|
// file is distributed with the modified code.
|
||||||
|
//
|
||||||
|
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||||
|
// By way of example, but not limitation, Licensor MAKES NO
|
||||||
|
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||||
|
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||||
|
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||||
|
// OR OTHER RIGHTS.
|
||||||
|
|
||||||
|
// Modyfied 2019 by Gundolf Haase, University of Graz
|
||||||
|
//=======================================================================
|
||||||
|
#include "cuthill_mckee_ordering.h"
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/graph/adjacency_list.hpp>
|
||||||
|
#include <boost/graph/bandwidth.hpp>
|
||||||
|
#include <boost/graph/cuthill_mckee_ordering.hpp>
|
||||||
|
#include <boost/graph/properties.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sample Output
|
||||||
|
original bandwidth: 8
|
||||||
|
Reverse Cuthill-McKee ordering starting at: 6
|
||||||
|
8 3 0 9 2 5 1 4 7 6
|
||||||
|
bandwidth: 4
|
||||||
|
Reverse Cuthill-McKee ordering starting at: 0
|
||||||
|
9 1 4 6 7 2 8 5 3 0
|
||||||
|
bandwidth: 4
|
||||||
|
Reverse Cuthill-McKee ordering:
|
||||||
|
0 8 5 7 3 6 4 2 1 9
|
||||||
|
bandwidth: 4
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
int main(int, char *[])
|
||||||
|
{
|
||||||
|
using namespace boost;
|
||||||
|
using namespace std;
|
||||||
|
typedef adjacency_list<vecS, vecS, undirectedS,
|
||||||
|
property<vertex_color_t, default_color_type,
|
||||||
|
property<vertex_degree_t, int> > > Graph;
|
||||||
|
typedef graph_traits<Graph>::vertex_descriptor Vertex;
|
||||||
|
typedef graph_traits<Graph>::vertices_size_type size_type;
|
||||||
|
|
||||||
|
typedef std::pair<std::size_t, std::size_t> Pair;
|
||||||
|
Pair edges[14] = { Pair(0, 3), //a-d
|
||||||
|
Pair(0, 5), //a-f
|
||||||
|
Pair(1, 2), //b-c
|
||||||
|
Pair(1, 4), //b-e
|
||||||
|
Pair(1, 6), //b-g
|
||||||
|
Pair(1, 9), //b-j
|
||||||
|
Pair(2, 3), //c-d
|
||||||
|
Pair(2, 4), //c-e
|
||||||
|
Pair(3, 5), //d-f
|
||||||
|
Pair(3, 8), //d-i
|
||||||
|
Pair(4, 6), //e-g
|
||||||
|
Pair(5, 6), //f-g
|
||||||
|
Pair(5, 7), //f-h
|
||||||
|
Pair(6, 7)
|
||||||
|
}; //g-h
|
||||||
|
|
||||||
|
Graph G(10);
|
||||||
|
for (int i = 0; i < 14; ++i)
|
||||||
|
add_edge(edges[i].first, edges[i].second, G);
|
||||||
|
|
||||||
|
graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||||
|
|
||||||
|
property_map<Graph, vertex_degree_t>::type deg = get(vertex_degree, G);
|
||||||
|
for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
|
||||||
|
deg[*ui] = degree(*ui, G);
|
||||||
|
|
||||||
|
property_map<Graph, vertex_index_t>::type
|
||||||
|
index_map = get(vertex_index, G);
|
||||||
|
|
||||||
|
std::cout << "original bandwidth: " << bandwidth(G) << std::endl;
|
||||||
|
|
||||||
|
std::vector<Vertex> inv_perm(num_vertices(G));
|
||||||
|
std::vector<size_type> perm(num_vertices(G));
|
||||||
|
{
|
||||||
|
Vertex s = vertex(6, G);
|
||||||
|
//reverse cuthill_mckee_ordering
|
||||||
|
cuthill_mckee_ordering(G, s, inv_perm.rbegin(), get(vertex_color, G),
|
||||||
|
get(vertex_degree, G));
|
||||||
|
cout << "Reverse Cuthill-McKee ordering starting at: " << s << endl;
|
||||||
|
cout << " ";
|
||||||
|
for (std::vector<Vertex>::const_iterator i = inv_perm.begin();
|
||||||
|
i != inv_perm.end(); ++i)
|
||||||
|
cout << index_map[*i] << " ";
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
for (size_type c = 0; c != inv_perm.size(); ++c)
|
||||||
|
perm[index_map[inv_perm[c]]] = c;
|
||||||
|
std::cout << " bandwidth: "
|
||||||
|
<< bandwidth(G, make_iterator_property_map(&perm[0], index_map, perm[0]))
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vertex s = vertex(0, G);
|
||||||
|
//reverse cuthill_mckee_ordering
|
||||||
|
cuthill_mckee_ordering(G, s, inv_perm.rbegin(), get(vertex_color, G),
|
||||||
|
get(vertex_degree, G));
|
||||||
|
cout << "Reverse Cuthill-McKee ordering starting at: " << s << endl;
|
||||||
|
cout << " ";
|
||||||
|
for (std::vector<Vertex>::const_iterator i = inv_perm.begin();
|
||||||
|
i != inv_perm.end(); ++i)
|
||||||
|
cout << index_map[*i] << " ";
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
for (size_type c = 0; c != inv_perm.size(); ++c)
|
||||||
|
perm[index_map[inv_perm[c]]] = c;
|
||||||
|
std::cout << " bandwidth: "
|
||||||
|
<< bandwidth(G, make_iterator_property_map(&perm[0], index_map, perm[0]))
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//reverse cuthill_mckee_ordering
|
||||||
|
cuthill_mckee_ordering(G, inv_perm.rbegin(), get(vertex_color, G),
|
||||||
|
make_degree_map(G));
|
||||||
|
|
||||||
|
cout << "Reverse Cuthill-McKee ordering:" << endl;
|
||||||
|
cout << " ";
|
||||||
|
for (std::vector<Vertex>::const_iterator i = inv_perm.begin();
|
||||||
|
i != inv_perm.end(); ++i)
|
||||||
|
cout << index_map[*i] << " ";
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
for (size_type c = 0; c != inv_perm.size(); ++c)
|
||||||
|
perm[index_map[inv_perm[c]]] = c;
|
||||||
|
std::cout << " bandwidth: "
|
||||||
|
<< bandwidth(G, make_iterator_property_map(&perm[0], index_map, perm[0]))
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// ------------- Modifications by Gundolf Haase
|
||||||
|
// std::vector<int> _edges; //!< edges of mesh (vertices ordered ascending)
|
||||||
|
|
||||||
|
using namespace boost;
|
||||||
|
using namespace std;
|
||||||
|
typedef adjacency_list<vecS, vecS, undirectedS,
|
||||||
|
property<vertex_color_t, default_color_type,
|
||||||
|
property<vertex_degree_t, int> > > Graph;
|
||||||
|
typedef graph_traits<Graph>::vertex_descriptor Vertex;
|
||||||
|
typedef graph_traits<Graph>::vertices_size_type size_type;
|
||||||
|
|
||||||
|
typedef std::pair<std::size_t, std::size_t> Pair;
|
||||||
|
|
||||||
|
vector<int> cuthill_mckee_reordering(vector<int> const &_edges)
|
||||||
|
{
|
||||||
|
size_t const nnodes = *max_element(cbegin(_edges), cend(_edges)) + 1;
|
||||||
|
cout << "NNODES = " << nnodes << endl;
|
||||||
|
//size_t const nedges = _edges.size()/2;
|
||||||
|
|
||||||
|
Graph G(nnodes);
|
||||||
|
for (size_t i = 0; i < _edges.size(); i+=2)
|
||||||
|
add_edge(_edges[i], _edges[i+1], G);
|
||||||
|
|
||||||
|
graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||||
|
|
||||||
|
property_map<Graph, vertex_degree_t>::type deg = get(vertex_degree, G);
|
||||||
|
for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
|
||||||
|
deg[*ui] = degree(*ui, G);
|
||||||
|
|
||||||
|
property_map<Graph, vertex_index_t>::type
|
||||||
|
index_map = get(vertex_index, G);
|
||||||
|
|
||||||
|
std::cout << "original bandwidth: " << bandwidth(G) << std::endl;
|
||||||
|
|
||||||
|
std::vector<Vertex> inv_perm(num_vertices(G));
|
||||||
|
//std::vector<size_type> perm(num_vertices(G));
|
||||||
|
std::vector<int> perm(num_vertices(G));
|
||||||
|
|
||||||
|
{
|
||||||
|
Vertex s = vertex(nnodes/2, G);
|
||||||
|
//reverse cuthill_mckee_ordering
|
||||||
|
cuthill_mckee_ordering(G, s, inv_perm.rbegin(), get(vertex_color, G),
|
||||||
|
get(vertex_degree, G));
|
||||||
|
//cout << "Reverse Cuthill-McKee ordering starting at: " << s << endl;
|
||||||
|
//cout << " ";
|
||||||
|
//for (std::vector<Vertex>::const_iterator i = inv_perm.begin(); i != inv_perm.end(); ++i)
|
||||||
|
//cout << index_map[*i] << " ";
|
||||||
|
//cout << endl;
|
||||||
|
|
||||||
|
for (size_type c = 0; c != inv_perm.size(); ++c)
|
||||||
|
perm[index_map[inv_perm[c]]] = c;
|
||||||
|
std::cout << "improved bandwidth: "
|
||||||
|
<< bandwidth(G, make_iterator_property_map(&perm[0], index_map, perm[0]))
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(perm.size()==nnodes);
|
||||||
|
|
||||||
|
return perm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------- end Modifications
|
||||||
|
|
||||||
|
|
||||||
8
sheet7/jacobi.template/cuthill_mckee_ordering.h
Normal file
8
sheet7/jacobi.template/cuthill_mckee_ordering.h
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef CUTHILL_MCKEE_ORDERING
|
||||||
|
#define CUTHILL_MCKEE_ORDERING
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::vector<int> cuthill_mckee_reordering(std::vector<int> const &_edges);
|
||||||
|
|
||||||
|
#endif
|
||||||
1277
sheet7/jacobi.template/geom.cpp
Normal file
1277
sheet7/jacobi.template/geom.cpp
Normal file
File diff suppressed because it is too large
Load diff
712
sheet7/jacobi.template/geom.h
Normal file
712
sheet7/jacobi.template/geom.h
Normal file
|
|
@ -0,0 +1,712 @@
|
||||||
|
#ifndef GEOM_FILE
|
||||||
|
#define GEOM_FILE
|
||||||
|
#include <array>
|
||||||
|
#include <functional> // function; C++11
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory> // shared_ptr
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basis class for finite element meshes.
|
||||||
|
*/
|
||||||
|
class Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor initializing the members with default values.
|
||||||
|
*
|
||||||
|
* @param[in] ndim space dimensions (dimension for coordinates)
|
||||||
|
* @param[in] nvert_e number of vertices per element (dimension for connectivity)
|
||||||
|
* @param[in] ndof_e degrees of freedom per element (= @p nvert_e for linear elements)
|
||||||
|
* @param[in] nedge_e number of edges per element (= @p nvert_e for linear elements in 2D)
|
||||||
|
*/
|
||||||
|
explicit Mesh(int ndim, int nvert_e = 0, int ndof_e = 0, int nedge_e = 0);
|
||||||
|
|
||||||
|
__attribute__((noinline))
|
||||||
|
Mesh(Mesh const &) = default;
|
||||||
|
|
||||||
|
Mesh &operator=(Mesh const &) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*
|
||||||
|
* See clang warning on
|
||||||
|
* <a href="https://stackoverflow.com/questions/28786473/clang-no-out-of-line-virtual-method-definitions-pure-abstract-c-class/40550578">weak-vtables</a>.
|
||||||
|
*/
|
||||||
|
virtual ~Mesh();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* File format, see ascii_write_mesh.m
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
*/
|
||||||
|
explicit Mesh(std::string const &fname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* File format, see ascii_write_mesh.m
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
*/
|
||||||
|
void ReadVertexBasedMesh(std::string const &fname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of finite elements in (sub)domain.
|
||||||
|
* @return number of elements.
|
||||||
|
*/
|
||||||
|
int Nelems() const
|
||||||
|
{
|
||||||
|
return _nelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of vertices for each finite element.
|
||||||
|
* @return number of vertices per element.
|
||||||
|
*/
|
||||||
|
int NverticesElements() const
|
||||||
|
{
|
||||||
|
return _nvert_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of degrees of freedom (dof) for each finite element.
|
||||||
|
* @return degrees of freedom per element.
|
||||||
|
*/
|
||||||
|
int NdofsElement() const
|
||||||
|
{
|
||||||
|
return _ndof_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of vertices in mesh.
|
||||||
|
* @return number of vertices.
|
||||||
|
*/
|
||||||
|
int Nnodes() const
|
||||||
|
{
|
||||||
|
return _nnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Space dimension.
|
||||||
|
* @return number of dimensions.
|
||||||
|
*/
|
||||||
|
int Ndims() const
|
||||||
|
{
|
||||||
|
return _ndim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re-)Allocates memory for the element connectivity and redefines the appropriate dimensions.
|
||||||
|
*
|
||||||
|
* @param[in] nelem number of elements
|
||||||
|
* @param[in] nvert_e number of vertices per element
|
||||||
|
*/
|
||||||
|
void Resize_Connectivity(int nelem, int nvert_e)
|
||||||
|
{
|
||||||
|
SetNelem(nelem); // number of elements
|
||||||
|
SetNverticesElement(nvert_e); // vertices per element
|
||||||
|
_ia.resize(nelem * nvert_e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read connectivity information (g1,g2,g3)_i.
|
||||||
|
* @return connectivity vector [nelems*ndofs].
|
||||||
|
*/
|
||||||
|
const std::vector<int> &GetConnectivity() const
|
||||||
|
{
|
||||||
|
return _ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change connectivity information (g1,g2,g3)_i.
|
||||||
|
* @return connectivity vector [nelems*ndofs].
|
||||||
|
*/
|
||||||
|
std::vector<int> &GetConnectivity()
|
||||||
|
{
|
||||||
|
return _ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re-)Allocates memory for the element connectivity and redefines the appropriate dimensions.
|
||||||
|
*
|
||||||
|
* @param[in] nnodes number of nodes
|
||||||
|
* @param[in] ndim space dimension
|
||||||
|
*/
|
||||||
|
void Resize_Coords(int nnodes, int ndim)
|
||||||
|
{
|
||||||
|
SetNnode(nnodes); // number of nodes
|
||||||
|
SetNdim(ndim); // space dimension
|
||||||
|
_xc.resize(nnodes * ndim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read coordinates of vertices (x,y)_i.
|
||||||
|
* @return coordinates vector [nnodes*2].
|
||||||
|
*/
|
||||||
|
const std::vector<double> &GetCoords() const
|
||||||
|
{
|
||||||
|
return _xc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change coordinates of vertices (x,y)_i.
|
||||||
|
* @return coordinates vector [nnodes*2].
|
||||||
|
*/
|
||||||
|
std::vector<double> &GetCoords()
|
||||||
|
{
|
||||||
|
return _xc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate values in vector @p v via function @p func(x,y)
|
||||||
|
* @param[in] v vector
|
||||||
|
* @param[in] func function of (x,y) returning a double value.
|
||||||
|
*/
|
||||||
|
void SetValues(std::vector<double> &v, const std::function<double(double, double)> &func) const;
|
||||||
|
void SetBoundaryValues(std::vector<double> &v, const std::function<double(double, double)> &func) const;
|
||||||
|
void SetDirchletValues(std::vector<double> &v, const std::function<double(double, double)> &func) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the information for a finite element mesh
|
||||||
|
*/
|
||||||
|
void Debug() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the edge based information for a finite element mesh
|
||||||
|
*/
|
||||||
|
void DebugEdgeBased() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
virtual std::vector<int> Index_DirichletNodes() const;
|
||||||
|
virtual std::vector<int> Index_BoundaryNodes() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write vector @p v together with its mesh information to an ASCii file @p fname.
|
||||||
|
*
|
||||||
|
* The data are written in C-style.
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
* @param[in] v vector
|
||||||
|
*/
|
||||||
|
void Write_ascii_matlab(std::string const &fname, std::vector<double> const &v) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports the mesh information to ASCii files @p basename + {_coords|_elements}.txt.
|
||||||
|
*
|
||||||
|
* The data are written in C-style.
|
||||||
|
*
|
||||||
|
* @param[in] basename first part of file names
|
||||||
|
*/
|
||||||
|
void Export_scicomp(std::string const &basename) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualize @p v together with its mesh information via matlab or octave.
|
||||||
|
*
|
||||||
|
* Comment/uncomment those code lines in method Mesh:Visualize (geom.cpp)
|
||||||
|
* that are supported on your system.
|
||||||
|
*
|
||||||
|
* @param[in] v vector
|
||||||
|
*
|
||||||
|
* @warning matlab files ascii_read_meshvector.m visualize_results.m
|
||||||
|
* must be in the executing directory.
|
||||||
|
*/
|
||||||
|
virtual void Visualize(std::vector<double> const &v) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of edges.
|
||||||
|
* @return number of edges in mesh.
|
||||||
|
*/
|
||||||
|
int Nedges() const
|
||||||
|
{
|
||||||
|
return _nedge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of edges for each finite element.
|
||||||
|
* @return number of edges per element.
|
||||||
|
*/
|
||||||
|
int NedgesElements() const
|
||||||
|
{
|
||||||
|
return _nedge_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read edge connectivity information (e1,e2,e3)_i.
|
||||||
|
* @return edge connectivity vector [nelems*_nedge_e].
|
||||||
|
*/
|
||||||
|
const std::vector<int> &GetEdgeConnectivity() const
|
||||||
|
{
|
||||||
|
return _ea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change edge connectivity information (e1,e2,e3)_i.
|
||||||
|
* @return edge connectivity vector [nelems*_nedge_e].
|
||||||
|
*/
|
||||||
|
std::vector<int> &GetEdgeConnectivity()
|
||||||
|
{
|
||||||
|
return _ea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read edge information (v1,v2)_i.
|
||||||
|
* @return edge connectivity vector [_nedge*2].
|
||||||
|
*/
|
||||||
|
const std::vector<int> &GetEdges() const
|
||||||
|
{
|
||||||
|
return _edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change edge information (v1,v2)_i.
|
||||||
|
* @return edge connectivity vector [_nedge*2].
|
||||||
|
*/
|
||||||
|
std::vector<int> &GetEdges()
|
||||||
|
{
|
||||||
|
return _edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines all node to node connections from the vertex based mesh.
|
||||||
|
*
|
||||||
|
* @return vector[k][] containing all connections of vertex k, including to itself.
|
||||||
|
*/
|
||||||
|
std::vector<std::vector<int>> Node2NodeGraph() const
|
||||||
|
{
|
||||||
|
//// Check version 2 wrt. version 1
|
||||||
|
//auto v1=Node2NodeGraph_1();
|
||||||
|
//auto v2=Node2NodeGraph_2();
|
||||||
|
//if ( equal(v1.cbegin(),v1.cend(),v2.begin()) )
|
||||||
|
//{
|
||||||
|
//std::cout << "\nidentical Versions\n";
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
//std::cout << "\nE R R O R in Versions\n";
|
||||||
|
//}
|
||||||
|
|
||||||
|
//return Node2NodeGraph_1();
|
||||||
|
return Node2NodeGraph_2(); // 2 times faster than version 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the father-of-nodes relation.
|
||||||
|
*
|
||||||
|
* @return vector of length 0 because no relation available.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
virtual std::vector<int> const &GetFathersOfVertices() const
|
||||||
|
{
|
||||||
|
return _dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all edge connectivity information (saves memory).
|
||||||
|
*/
|
||||||
|
void Del_EdgeConnectivity();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//public:
|
||||||
|
void SetNelem(int nelem)
|
||||||
|
{
|
||||||
|
_nelem = nelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNverticesElement(int nvert)
|
||||||
|
{
|
||||||
|
_nvert_e = nvert;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNdofsElement(int ndof)
|
||||||
|
{
|
||||||
|
_ndof_e = ndof;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNnode(int nnode)
|
||||||
|
{
|
||||||
|
_nnode = nnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNdim(int ndim)
|
||||||
|
{
|
||||||
|
_ndim = ndim;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNedge(int nedge)
|
||||||
|
{
|
||||||
|
_nedge = nedge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads vertex based mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* File format, see ascii_write_mesh.m
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
*/
|
||||||
|
void ReadVectexBasedMesh(std::string const &fname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The vertex based mesh data are used to derive the edge based data.
|
||||||
|
*
|
||||||
|
* @warning Exactly 3 vertices, 3 edges per element are assumed (linear triangle in 2D)
|
||||||
|
*/
|
||||||
|
void DeriveEdgeFromVertexBased()
|
||||||
|
{
|
||||||
|
//DeriveEdgeFromVertexBased_slow();
|
||||||
|
//DeriveEdgeFromVertexBased_fast();
|
||||||
|
DeriveEdgeFromVertexBased_fast_2();
|
||||||
|
}
|
||||||
|
void DeriveEdgeFromVertexBased_slow();
|
||||||
|
void DeriveEdgeFromVertexBased_fast();
|
||||||
|
void DeriveEdgeFromVertexBased_fast_2();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The edge based mesh data are used to derive the vertex based data.
|
||||||
|
*
|
||||||
|
* @warning Exactly 3 vertices, 3 edges per element are assumed (linear triangle in 2D)
|
||||||
|
*/
|
||||||
|
void DeriveVertexFromEdgeBased();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
int Nnbedges() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(_bedges.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the array dimensions fit to their appropriate size parameters
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
virtual bool Check_array_dimensions() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permutes the vertex information in an edge based mesh.
|
||||||
|
*
|
||||||
|
* @param[in] old2new new indices of original vertices.
|
||||||
|
*/
|
||||||
|
void PermuteVertices_EdgeBased(std::vector<int> const &old2new);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Determines all node to node connections from the vertex based mesh.
|
||||||
|
*
|
||||||
|
* @return vector[k][] containing all connections of vertex k, including to itself.
|
||||||
|
*/
|
||||||
|
std::vector<std::vector<int>> Node2NodeGraph_1() const; // is correct
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines all node to node connections from the vertex based mesh.
|
||||||
|
*
|
||||||
|
* Faster than @p Node2NodeGraph_1().
|
||||||
|
*
|
||||||
|
* @return vector[k][] containing all connections of vertex k, including to itself.
|
||||||
|
*/
|
||||||
|
std::vector<std::vector<int>> Node2NodeGraph_2() const; // is correct
|
||||||
|
|
||||||
|
//private:
|
||||||
|
protected:
|
||||||
|
int _nelem; //!< number elements
|
||||||
|
int _nvert_e; //!< number of vertices per element
|
||||||
|
int _ndof_e; //!< degrees of freedom (d.o.f.) per element
|
||||||
|
int _nnode; //!< number nodes/vertices
|
||||||
|
int _ndim; //!< space dimension of the problem (1, 2, or 3)
|
||||||
|
std::vector<int> _ia; //!< element connectivity
|
||||||
|
std::vector<double> _xc; //!< coordinates
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// B.C.
|
||||||
|
std::vector<int> _bedges; //!< boundary edges [nbedges][2] storing start/end vertex
|
||||||
|
// 2020-01-08
|
||||||
|
std::vector<int> _sdedges; //!< boundary edges [nbedges][2] with left/right subdomain number
|
||||||
|
|
||||||
|
//private:
|
||||||
|
protected:
|
||||||
|
// edge based connectivity
|
||||||
|
int _nedge; //!< number of edges in mesh
|
||||||
|
int _nedge_e; //!< number of edges per element
|
||||||
|
std::vector<int> _edges; //!< edges of mesh (vertices ordered ascending)
|
||||||
|
std::vector<int> _ea; //!< edge based element connectivity
|
||||||
|
// B.C.
|
||||||
|
std::vector<int> _ebedges; //!< boundary edges [nbedges]
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<int> _dummy; //!< empty dummy vector
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
class RefinedMesh: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructs a refined mesh according to the marked elements in @p ibref.
|
||||||
|
*
|
||||||
|
* If the vector @p ibref has size 0 then all elements will be refined.
|
||||||
|
*
|
||||||
|
* @param[in] cmesh original mesh for coarsening.
|
||||||
|
* @param[in] ibref vector containing True/False regarding refinement for each element
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//explicit RefinedMesh(Mesh const &cmesh, std::vector<bool> const &ibref = std::vector<bool>(0));
|
||||||
|
RefinedMesh(Mesh const &cmesh, std::vector<bool> const &ibref);
|
||||||
|
//RefinedMesh(Mesh const &cmesh, std::vector<bool> const &ibref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a refined mesh by regulare refinement of all elements.
|
||||||
|
*
|
||||||
|
* @param[in] cmesh original mesh for coarsening.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
explicit RefinedMesh(Mesh const &cmesh)
|
||||||
|
: RefinedMesh(cmesh, std::vector<bool>(0))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
RefinedMesh(RefinedMesh const &) = delete;
|
||||||
|
//RefinedMesh(RefinedMesh const&&) = delete;
|
||||||
|
|
||||||
|
RefinedMesh &operator=(RefinedMesh const &) = delete;
|
||||||
|
//RefinedMesh& operator=(RefinedMesh const&&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~RefinedMesh() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refines the mesh according to the marked elements.
|
||||||
|
*
|
||||||
|
* @param[in] ibref vector containing True/False regarding refinement for each element
|
||||||
|
*
|
||||||
|
* @return the refined mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh RefineElements(std::vector<bool> const &ibref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refines all elements in the actual mesh.
|
||||||
|
*
|
||||||
|
* @param[in] nref number of regular refinements to perform
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void RefineAllElements(int nref = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the father-of-nodes relation.
|
||||||
|
*
|
||||||
|
* @return father-of-nodes relation [nnodes][2]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
std::vector<int> const &GetFathersOfVertices() const override
|
||||||
|
{
|
||||||
|
return _vfathers;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Checks whether the array dimensions fit to their appropriate size parameters
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
bool Check_array_dimensions() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permutes the vertex information in an edge based mesh.
|
||||||
|
*
|
||||||
|
* @param[in] old2new new indices of original vertices.
|
||||||
|
*/
|
||||||
|
void PermuteVertices_EdgeBased(std::vector<int> const &old2new);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//Mesh const & _cmesh; //!< coarse mesh
|
||||||
|
std::vector<bool> const _ibref; //!< refinement info
|
||||||
|
int _nref; //!< number of regular refinements performed
|
||||||
|
std::vector<int> _vfathers; //!< stores the 2 fathers of each vertex (equal fathers denote original coarse vertex)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
class gMesh_Hierarchy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructs mesh hierarchy of @p nlevel levels starting with coarse mesh @p cmesh.
|
||||||
|
* The coarse mesh @p cmesh will be @p nlevel-1 times geometrically refined.
|
||||||
|
*
|
||||||
|
* @param[in] cmesh initial coarse mesh
|
||||||
|
* @param[in] nlevel number levels in mesh hierarchy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
gMesh_Hierarchy(Mesh const &cmesh, int nlevel);
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
return _gmesh.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to mesh @p lev from mesh hierarchy.
|
||||||
|
*
|
||||||
|
* @return mesh @p lev
|
||||||
|
* @warning An out_of_range exception might be thrown.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh const &operator[](int lev) const
|
||||||
|
{
|
||||||
|
return *_gmesh.at(lev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to finest mesh in mesh hierarchy.
|
||||||
|
*
|
||||||
|
* @return finest mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh const &finest() const
|
||||||
|
{
|
||||||
|
return *_gmesh.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to coarest mesh in mesh hierarchy.
|
||||||
|
*
|
||||||
|
* @return coarsest mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Mesh const &coarsest() const
|
||||||
|
{
|
||||||
|
return *_gmesh.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<Mesh>> _gmesh; //!< mesh hierarchy from coarse ([0]) to fine.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
/**
|
||||||
|
* 2D finite element mesh of the square consisting of linear triangular elements.
|
||||||
|
*/
|
||||||
|
class Mesh_2d_3_square: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Generates the f.e. mesh for the unit square.
|
||||||
|
*
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in] myid my MPI-rank / subdomain
|
||||||
|
* @param[in] procx number of ranks/subdomains in x-direction
|
||||||
|
* @param[in] procy number of processes in y-direction
|
||||||
|
*/
|
||||||
|
Mesh_2d_3_square(int nx, int ny, int myid = 0, int procx = 1, int procy = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
~Mesh_2d_3_square() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set solution vector based on a tensor product grid in the rectangle.
|
||||||
|
* @param[in] u solution vector
|
||||||
|
*/
|
||||||
|
void SetU(std::vector<double> &u) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set right hand side (rhs) vector on a tensor product grid in the rectangle.
|
||||||
|
* @param[in] f rhs vector
|
||||||
|
*/
|
||||||
|
void SetF(std::vector<double> &f) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
std::vector<int> Index_DirichletNodes() const override;
|
||||||
|
std::vector<int> Index_BoundaryNodes() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the values of vector @p u of (sub)domain into a file @p name for further processing in gnuplot.
|
||||||
|
* The file stores rowise the x- and y- coordinates together with the value from @p u .
|
||||||
|
* The domain [@p xl, @p xr] x [@p yb, @p yt] is discretized into @p nx x @p ny intervals.
|
||||||
|
*
|
||||||
|
* @param[in] name basename of file name (file name will be extended by the rank number)
|
||||||
|
* @param[in] u local vector
|
||||||
|
*
|
||||||
|
* @warning Assumes tensor product grid in unit square; rowise numbered
|
||||||
|
* (as generated in class constructor).
|
||||||
|
* The output is provided for tensor product grid visualization
|
||||||
|
* ( similar to Matlab-surf() ).
|
||||||
|
*
|
||||||
|
* @see Mesh_2d_3_square
|
||||||
|
*/
|
||||||
|
void SaveVectorP(std::string const &name, std::vector<double> const &u) const;
|
||||||
|
|
||||||
|
// here will still need to implement in the class
|
||||||
|
// GetBound(), AddBound()
|
||||||
|
// or better a generalized way with indices and their appropriate ranks for MPI communication
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Determines the coordinates of the discretization nodes of the domain [@p xl, @p xr] x [@p yb, @p yt]
|
||||||
|
* which is discretized into @p nx x @p ny intervals.
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in] xl x-coordinate of left boundary
|
||||||
|
* @param[in] xr x-coordinate of right boundary
|
||||||
|
* @param[in] yb y-coordinate of lower boundary
|
||||||
|
* @param[in] yt y-coordinate of upper boundary
|
||||||
|
* @param[out] xc coordinate vector of length 2n with x(2*k,2*k+1) as coordinates of node k
|
||||||
|
*/
|
||||||
|
|
||||||
|
void GetCoordsInRectangle(int nx, int ny, double xl, double xr, double yb, double yt,
|
||||||
|
double xc[]);
|
||||||
|
/**
|
||||||
|
* Determines the element connectivity of linear triangular elements of a FEM discretization
|
||||||
|
* of a rectangle using @p nx x @p ny equidistant intervals for discretization.
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[out] ia element connectivity matrix with ia(3*s,3*s+1,3*s+2) as node numbers od element s
|
||||||
|
*/
|
||||||
|
void GetConnectivityInRectangle(int nx, int ny, int ia[]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _myid; //!< my MPI rank
|
||||||
|
int _procx; //!< number of MPI ranks in x-direction
|
||||||
|
int _procy; //!< number of MPI ranks in y-direction
|
||||||
|
std::array<int, 4> _neigh; //!< MPI ranks of neighbors (negative: no neighbor but b.c.)
|
||||||
|
int _color; //!< red/black coloring (checker board) of subdomains
|
||||||
|
|
||||||
|
double _xl; //!< x coordinate of lower left corner of square
|
||||||
|
double _xr; //!< x coordinate of lower right corner of square
|
||||||
|
double _yb; //!< y coordinate or lower left corner of square
|
||||||
|
double _yt; //!< y coordinate of upper right corner of square
|
||||||
|
int _nx; //!< number of intervals in x-direction
|
||||||
|
int _ny; //!< number of intervals in y-direction
|
||||||
|
};
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
720
sheet7/jacobi.template/getmatrix.cpp
Normal file
720
sheet7/jacobi.template/getmatrix.cpp
Normal file
|
|
@ -0,0 +1,720 @@
|
||||||
|
#include "getmatrix.h"
|
||||||
|
#include "userset.h"
|
||||||
|
|
||||||
|
#include "omp.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <ctime> // contains clock()
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// ####################################################################
|
||||||
|
|
||||||
|
Matrix::Matrix(int const nrows, int const ncols)
|
||||||
|
: _nrows(nrows), _ncols(ncols), _dd(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//Matrix::Matrix()
|
||||||
|
//: Matrix(0,0)
|
||||||
|
//{}
|
||||||
|
|
||||||
|
|
||||||
|
Matrix::~Matrix()
|
||||||
|
{}
|
||||||
|
|
||||||
|
//vector<double> const & Matrix::GetDiag() const
|
||||||
|
//{
|
||||||
|
//if ( 0==_dd.size() )
|
||||||
|
//{
|
||||||
|
//_dd.resize(Nrows());
|
||||||
|
//this->GetDiag(_dd);
|
||||||
|
//}
|
||||||
|
//assert( Nrows()==static_cast<int>(_dd.size()) );
|
||||||
|
//return _dd;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// ####################################################################
|
||||||
|
|
||||||
|
CRS_Matrix::CRS_Matrix()
|
||||||
|
: Matrix(0,0), _nnz(0), _id(0), _ik(0), _sk(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CRS_Matrix::~CRS_Matrix()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CRS_Matrix::Mult(vector<double> &w, vector<double> const &u) const
|
||||||
|
{
|
||||||
|
assert( _ncols==static_cast<int>(u.size()) ); // compatibility of inner dimensions
|
||||||
|
assert( _nrows==static_cast<int>(w.size()) ); // compatibility of outer dimensions
|
||||||
|
|
||||||
|
for (int row = 0; row < _nrows; ++row)
|
||||||
|
{
|
||||||
|
double wi = 0.0;
|
||||||
|
for (int ij = _id[row]; ij < _id[row + 1]; ++ij)
|
||||||
|
{
|
||||||
|
wi += _sk[ij] * u[ _ik[ij] ];
|
||||||
|
}
|
||||||
|
w[row] = wi;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRS_Matrix::Defect(vector<double> &w,
|
||||||
|
vector<double> const &f, vector<double> const &u) const
|
||||||
|
{
|
||||||
|
assert( _ncols==static_cast<int>(u.size()) ); // compatibility of inner dimensions
|
||||||
|
assert( _nrows==static_cast<int>(w.size()) ); // compatibility of outer dimensions
|
||||||
|
assert( w.size()==f.size() );
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int row = 0; row < _nrows; ++row)
|
||||||
|
{
|
||||||
|
double wi = f[row];
|
||||||
|
for (int ij = _id[row]; ij < _id[row + 1]; ++ij)
|
||||||
|
{
|
||||||
|
wi -= _sk[ij] * u[ _ik[ij] ];
|
||||||
|
}
|
||||||
|
w[row] = wi;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRS_Matrix::GetDiag(vector<double> &d) const
|
||||||
|
{
|
||||||
|
// be carefull when using a rectangular matrix
|
||||||
|
int const nm = min(_nrows, _ncols);
|
||||||
|
|
||||||
|
assert( nm==static_cast<int>(d.size()) ); // instead of stopping we could resize d and warn the user
|
||||||
|
|
||||||
|
for (int row = 0; row < nm; ++row)
|
||||||
|
{
|
||||||
|
const int ia = fetch(row, row); // Find diagonal entry of row
|
||||||
|
assert(ia >= 0);
|
||||||
|
d[row] = _sk[ia];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
int CRS_Matrix::fetch(int const row, int const col) const
|
||||||
|
{
|
||||||
|
int const id2 = _id[row + 1]; // end and
|
||||||
|
int ip = _id[row]; // start of recent row (global index)
|
||||||
|
|
||||||
|
while (ip < id2 && _ik[ip] != col) // find index col (global index)
|
||||||
|
{
|
||||||
|
++ip;
|
||||||
|
}
|
||||||
|
if (ip >= id2)
|
||||||
|
{
|
||||||
|
ip = -1;
|
||||||
|
#ifndef NDEBUG // compiler option -DNDEBUG switches off the check
|
||||||
|
cout << "No column " << col << " in row " << row << endl;
|
||||||
|
assert(ip >= id2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRS_Matrix::Debug() const
|
||||||
|
{
|
||||||
|
// ID points to first entry of row
|
||||||
|
// no symmetry assumed
|
||||||
|
cout << "\nMatrix (" << _nrows << " x " << _ncols << " with nnz = " << _id[_nrows] << ")\n";
|
||||||
|
|
||||||
|
for (int row = 0; row < _nrows; ++row)
|
||||||
|
{
|
||||||
|
cout << "Row " << row << " : ";
|
||||||
|
int const id1 = _id[row];
|
||||||
|
int const id2 = _id[row + 1];
|
||||||
|
for (int j = id1; j < id2; ++j)
|
||||||
|
{
|
||||||
|
cout.setf(ios::right, ios::adjustfield);
|
||||||
|
cout << "[" << setw(2) << _ik[j] << "] " << setw(4) << _sk[j] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool CRS_Matrix::Compare2Old(int nnode, int const id[], int const ik[], double const sk[]) const
|
||||||
|
{
|
||||||
|
bool bn = (nnode==_nrows); // number of rows
|
||||||
|
if (!bn)
|
||||||
|
{
|
||||||
|
cout << "######### Error: " << "number of rows" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bz = (id[nnode]==_nnz); // number of non zero elements
|
||||||
|
if (!bz)
|
||||||
|
{
|
||||||
|
cout << "######### Error: " << "number of non zero elements" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bd = equal(id,id+nnode+1,_id.cbegin()); // row starts
|
||||||
|
if (!bd)
|
||||||
|
{
|
||||||
|
cout << "######### Error: " << "row starts" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bk = equal(ik,ik+id[nnode],_ik.cbegin()); // column indices
|
||||||
|
if (!bk)
|
||||||
|
{
|
||||||
|
cout << "######### Error: " << "column indices" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bv = equal(sk,sk+id[nnode],_sk.cbegin()); // values
|
||||||
|
if (!bv)
|
||||||
|
{
|
||||||
|
cout << "######### Error: " << "values" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bn && bz && bd && bk && bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ####################################################################
|
||||||
|
|
||||||
|
FEM_Matrix::FEM_Matrix(Mesh const & mesh)
|
||||||
|
: CRS_Matrix(), _mesh(mesh)
|
||||||
|
{
|
||||||
|
Derive_Matrix_Pattern();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FEM_Matrix::~FEM_Matrix()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void FEM_Matrix::Derive_Matrix_Pattern_fast()
|
||||||
|
{
|
||||||
|
cout << "\n############ FEM_Matrix::Derive_Matrix_Pattern ";
|
||||||
|
double tstart = clock();
|
||||||
|
int const nelem(_mesh.Nelems());
|
||||||
|
int const ndof_e(_mesh.NdofsElement());
|
||||||
|
auto const &ia(_mesh.GetConnectivity());
|
||||||
|
// Determine the number of matrix rows
|
||||||
|
_nrows = *max_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem);
|
||||||
|
++_nrows; // node numberng: 0 ... nnode-1
|
||||||
|
assert(*min_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem) == 0); // numbering starts with 0 ?
|
||||||
|
|
||||||
|
// CSR data allocation
|
||||||
|
_id.resize(_nrows + 1); // Allocate memory for CSR row pointer
|
||||||
|
//##########################################################################
|
||||||
|
auto const v2v=_mesh.Node2NodeGraph();
|
||||||
|
_nnz=0; // number of connections
|
||||||
|
_id[0] = 0; // start of matrix row zero
|
||||||
|
for (size_t v = 0; v<v2v.size(); ++v )
|
||||||
|
{
|
||||||
|
_id[v+1] = _id[v] + v2v[v].size();
|
||||||
|
_nnz += v2v[v].size();
|
||||||
|
}
|
||||||
|
assert(_nnz == _id[_nrows]);
|
||||||
|
_sk.resize(_nnz); // Allocate memory for CSR column index vector
|
||||||
|
|
||||||
|
// CSR data allocation
|
||||||
|
_ik.resize(_nnz); // Allocate memory for CSR column index vector
|
||||||
|
// Copy column indices
|
||||||
|
int kk = 0;
|
||||||
|
for (size_t v = 0; v<v2v.size(); ++v )
|
||||||
|
{
|
||||||
|
for (size_t vi=0; vi<v2v[v].size(); ++vi)
|
||||||
|
{
|
||||||
|
_ik[kk] = v2v[v][vi];
|
||||||
|
++kk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ncols = *max_element(_ik.cbegin(), _ik.cend()); // maximal column number
|
||||||
|
++_ncols; // node numbering: 0 ... nnode-1
|
||||||
|
//cout << _nrows << " " << _ncols << endl;
|
||||||
|
assert(_ncols==_nrows);
|
||||||
|
|
||||||
|
double duration = (clock() - tstart) / CLOCKS_PER_SEC;
|
||||||
|
cout << "finished in " << duration << " sec. ########\n";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FEM_Matrix::Derive_Matrix_Pattern_slow()
|
||||||
|
{
|
||||||
|
cout << "\n############ FEM_Matrix::Derive_Matrix_Pattern slow ";
|
||||||
|
double tstart = clock();
|
||||||
|
int const nelem(_mesh.Nelems());
|
||||||
|
int const ndof_e(_mesh.NdofsElement());
|
||||||
|
auto const &ia(_mesh.GetConnectivity());
|
||||||
|
// Determine the number of matrix rows
|
||||||
|
_nrows = *max_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem);
|
||||||
|
++_nrows; // node numberng: 0 ... nnode-1
|
||||||
|
assert(*min_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem) == 0); // numbering starts with 0 ?
|
||||||
|
|
||||||
|
// Collect for each node those nodes it is connected to (multiple entries)
|
||||||
|
// Detect the neighboring nodes
|
||||||
|
vector< list<int> > cc(_nrows); // cc[i] is the list of nodes a node i is connected to
|
||||||
|
for (int i = 0; i < nelem; ++i)
|
||||||
|
{
|
||||||
|
int const idx = ndof_e * i;
|
||||||
|
for (int k = 0; k < ndof_e; ++k)
|
||||||
|
{
|
||||||
|
list<int> &cck = cc[ia[idx + k]];
|
||||||
|
cck.insert( cck.end(), ia.cbegin() + idx, ia.cbegin() + idx + ndof_e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Delete the multiple entries
|
||||||
|
_nnz = 0;
|
||||||
|
for (auto &it : cc)
|
||||||
|
{
|
||||||
|
it.sort();
|
||||||
|
it.unique();
|
||||||
|
_nnz += it.size();
|
||||||
|
// cout << it.size() << " :: "; copy(it->begin(),it->end(), ostream_iterator<int,char>(cout," ")); cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSR data allocation
|
||||||
|
_id.resize(_nrows + 1); // Allocate memory for CSR row pointer
|
||||||
|
_ik.resize(_nnz); // Allocate memory for CSR column index vector
|
||||||
|
|
||||||
|
// copy CSR data
|
||||||
|
_id[0] = 0; // begin of first row
|
||||||
|
for (size_t i = 0; i < cc.size(); ++i)
|
||||||
|
{
|
||||||
|
//cout << i << " " << nid.at(i) << endl;;
|
||||||
|
const list<int> &ci = cc[i];
|
||||||
|
const auto nci = static_cast<int>(ci.size());
|
||||||
|
_id[i + 1] = _id[i] + nci; // begin of next line
|
||||||
|
copy(ci.begin(), ci.end(), _ik.begin() + _id[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_nnz == _id[_nrows]);
|
||||||
|
_sk.resize(_nnz); // Allocate memory for CSR column index vector
|
||||||
|
|
||||||
|
_ncols = *max_element(_ik.cbegin(), _ik.cend()); // maximal column number
|
||||||
|
++_ncols; // node numbering: 0 ... nnode-1
|
||||||
|
//cout << _nrows << " " << _ncols << endl;
|
||||||
|
assert(_ncols==_nrows);
|
||||||
|
|
||||||
|
double duration = (clock() - tstart) / CLOCKS_PER_SEC;
|
||||||
|
cout << "finished in " << duration << " sec. ########\n";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FEM_Matrix::CalculateLaplace(vector<double> &f)
|
||||||
|
{
|
||||||
|
cout << "\n############ FEM_Matrix::CalculateLaplace ";
|
||||||
|
//double tstart = clock();
|
||||||
|
double tstart = omp_get_wtime(); // OpenMP
|
||||||
|
assert(_mesh.NdofsElement() == 3); // only for triangular, linear elements
|
||||||
|
//cout << _nnz << " vs. " << _id[_nrows] << " " << _nrows<< endl;
|
||||||
|
assert(_nnz == _id[_nrows]);
|
||||||
|
|
||||||
|
for (int k = 0; k < _nrows; ++k)
|
||||||
|
{
|
||||||
|
_sk[k] = 0.0;
|
||||||
|
}
|
||||||
|
for (int k = 0; k < _nrows; ++k)
|
||||||
|
{
|
||||||
|
f[k] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ske[3][3], fe[3];
|
||||||
|
// Loop over all elements
|
||||||
|
auto const nelem = _mesh.Nelems();
|
||||||
|
auto const &ia = _mesh.GetConnectivity();
|
||||||
|
auto const &xc = _mesh.GetCoords();
|
||||||
|
|
||||||
|
#pragma omp parallel for private(ske,fe)
|
||||||
|
for (int i = 0; i < nelem; ++i)
|
||||||
|
{
|
||||||
|
CalcElem(ia.data()+3 * i, xc.data(), ske, fe);
|
||||||
|
//AddElem(ia.data()+3 * i, ske, fe, _id.data(), _ik.data(), _sk.data(), f.data()); // GH: deprecated
|
||||||
|
AddElem_3(ia.data()+3 * i, ske, fe, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//double duration = (clock() - tstart) / CLOCKS_PER_SEC;
|
||||||
|
double duration = omp_get_wtime() - tstart; // OpenMP
|
||||||
|
cout << "finished in " << duration << " sec. ########\n";
|
||||||
|
//Debug();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//void FEM_Matrix::ApplyDirichletBC(std::vector<double> const &u, std::vector<double> &f)
|
||||||
|
//{
|
||||||
|
//double const PENALTY = 1e6;
|
||||||
|
//auto const idx = _mesh.Index_DirichletNodes();
|
||||||
|
//int const nidx = idx.size();
|
||||||
|
|
||||||
|
//for (int i=0; i<nidx; ++i)
|
||||||
|
//{
|
||||||
|
//int const k = idx[i];
|
||||||
|
//int const id1 = fetch(k, k); // Find diagonal entry of k
|
||||||
|
//assert(id1 >= 0);
|
||||||
|
//_sk[id1] += PENALTY; // matrix weighted scaling feasible
|
||||||
|
//f[k] += PENALTY * u[k];
|
||||||
|
//}
|
||||||
|
|
||||||
|
//return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
void FEM_Matrix::ApplyDirichletBC(std::vector<double> const &u, std::vector<double> &f)
|
||||||
|
{
|
||||||
|
auto const idx = _mesh.Index_DirichletNodes();
|
||||||
|
int const nidx = idx.size();
|
||||||
|
|
||||||
|
for (int i=0; i<nidx; ++i)
|
||||||
|
{
|
||||||
|
int const row = idx[i];
|
||||||
|
for (int ij=_id[row]; ij<_id[row+1]; ++ij)
|
||||||
|
{
|
||||||
|
int const col=_ik[ij];
|
||||||
|
if (col==row)
|
||||||
|
{
|
||||||
|
_sk[ij] = 1.0;
|
||||||
|
f[row] = u[row];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int const id1 = fetch(col, row); // Find entry (col,row)
|
||||||
|
assert(id1 >= 0);
|
||||||
|
f[col] -= _sk[id1]*u[row];
|
||||||
|
_sk[id1] = 0.0;
|
||||||
|
_sk[ij] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FEM_Matrix::AddElem_3(int const ial[3], double const ske[3][3], double const fe[3], vector<double> & f)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
const int ii = ial[i]; // row ii (global index)
|
||||||
|
for (int j = 0; j < 3; ++j) // no symmetry assumed
|
||||||
|
{
|
||||||
|
const int jj = ial[j]; // column jj (global index)
|
||||||
|
const int ip = fetch(ii,jj); // find column entry jj in row ii
|
||||||
|
#ifndef NDEBUG // compiler option -DNDEBUG switches off the check
|
||||||
|
if (ip<0) // no entry found !!
|
||||||
|
{
|
||||||
|
cout << "Error in AddElem: (" << ii << "," << jj << ") ["
|
||||||
|
<< ial[0] << "," << ial[1] << "," << ial[2] << "]\n";
|
||||||
|
assert(ip>=0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#pragma omp atomic
|
||||||
|
_sk[ip] += ske[i][j];
|
||||||
|
}
|
||||||
|
#pragma omp atomic
|
||||||
|
f[ii] += fe[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ####################################################################
|
||||||
|
|
||||||
|
|
||||||
|
//Prolongation::Prolongation(Mesh const & cmesh, Mesh const & fmesh)
|
||||||
|
//: CRS_Matrix(), _cmesh(cmesh), _fmesh(fmesh)
|
||||||
|
//{
|
||||||
|
//Derive_Matrix_Pattern();
|
||||||
|
//return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
//void Prolongation::Derive_Matrix_Pattern()
|
||||||
|
//{
|
||||||
|
//cout << "\n ***** Subject to ongoing imlementation. *****\n";
|
||||||
|
//}
|
||||||
|
|
||||||
|
// ####################################################################
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
// general routine for lin. triangular elements
|
||||||
|
|
||||||
|
void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3])
|
||||||
|
//void CalcElem(const int* __restrict__ ial, const double* __restrict__ xc, double* __restrict__ ske[3], double* __restrict__ fe)
|
||||||
|
{
|
||||||
|
const int i1 = 2 * ial[0], i2 = 2 * ial[1], i3 = 2 * ial[2];
|
||||||
|
const double x13 = xc[i3 + 0] - xc[i1 + 0], y13 = xc[i3 + 1] - xc[i1 + 1],
|
||||||
|
x21 = xc[i1 + 0] - xc[i2 + 0], y21 = xc[i1 + 1] - xc[i2 + 1],
|
||||||
|
x32 = xc[i2 + 0] - xc[i3 + 0], y32 = xc[i2 + 1] - xc[i3 + 1];
|
||||||
|
const double jac = fabs(x21 * y13 - x13 * y21);
|
||||||
|
|
||||||
|
ske[0][0] = 0.5 / jac * (y32 * y32 + x32 * x32);
|
||||||
|
ske[0][1] = 0.5 / jac * (y13 * y32 + x13 * x32);
|
||||||
|
ske[0][2] = 0.5 / jac * (y21 * y32 + x21 * x32);
|
||||||
|
ske[1][0] = ske[0][1];
|
||||||
|
ske[1][1] = 0.5 / jac * (y13 * y13 + x13 * x13);
|
||||||
|
ske[1][2] = 0.5 / jac * (y21 * y13 + x21 * x13);
|
||||||
|
ske[2][0] = ske[0][2];
|
||||||
|
ske[2][1] = ske[1][2];
|
||||||
|
ske[2][2] = 0.5 / jac * (y21 * y21 + x21 * x21);
|
||||||
|
|
||||||
|
const double xm = (xc[i1 + 0] + xc[i2 + 0] + xc[i3 + 0]) / 3.0,
|
||||||
|
ym = (xc[i1 + 1] + xc[i2 + 1] + xc[i3 + 1]) / 3.0;
|
||||||
|
//fe[0] = fe[1] = fe[2] = 0.5 * jac * FunctF(xm, ym) / 3.0;
|
||||||
|
fe[0] = fe[1] = fe[2] = 0.5 * jac * fNice(xm, ym) / 3.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalcElem_Masse(int const ial[3], double const xc[], double const cm, double ske[3][3])
|
||||||
|
{
|
||||||
|
const int i1 = 2 * ial[0], i2 = 2 * ial[1], i3 = 2 * ial[2];
|
||||||
|
const double x13 = xc[i3 + 0] - xc[i1 + 0], y13 = xc[i3 + 1] - xc[i1 + 1],
|
||||||
|
x21 = xc[i1 + 0] - xc[i2 + 0], y21 = xc[i1 + 1] - xc[i2 + 1];
|
||||||
|
//x32 = xc[i2 + 0] - xc[i3 + 0], y32 = xc[i2 + 1] - xc[i3 + 1];
|
||||||
|
const double jac = fabs(x21 * y13 - x13 * y21);
|
||||||
|
|
||||||
|
ske[0][0] += jac/12.0;
|
||||||
|
ske[0][1] += jac/24.0;
|
||||||
|
ske[0][2] += jac/24.0;
|
||||||
|
ske[1][0] += jac/24.0;
|
||||||
|
ske[1][1] += jac/12.0;
|
||||||
|
ske[1][2] += jac/24.0;
|
||||||
|
ske[2][0] += jac/24.0;
|
||||||
|
ske[2][1] += jac/24.0;
|
||||||
|
ske[2][2] += jac/12.0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// general routine for lin. triangular elements,
|
||||||
|
// non-symm. matrix
|
||||||
|
// node numbering in element: a s c e n d i n g indices !!
|
||||||
|
// GH: deprecated
|
||||||
|
void AddElem(int const ial[3], double const ske[3][3], double const fe[3],
|
||||||
|
int const id[], int const ik[], double sk[], double f[])
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
const int ii = ial[i], // row ii (global index)
|
||||||
|
id1 = id[ii], // start and
|
||||||
|
id2 = id[ii + 1]; // end of row ii in matrix
|
||||||
|
int ip = id1;
|
||||||
|
for (int j = 0; j < 3; ++j) // no symmetry assumed
|
||||||
|
{
|
||||||
|
const int jj = ial[j];
|
||||||
|
bool not_found = true;
|
||||||
|
do // find entry jj (global index) in row ii
|
||||||
|
{
|
||||||
|
not_found = (ik[ip] != jj);
|
||||||
|
++ip;
|
||||||
|
}
|
||||||
|
while (not_found && ip < id2);
|
||||||
|
|
||||||
|
#ifndef NDEBUG // compiler option -DNDEBUG switches off the check
|
||||||
|
if (not_found) // no entry found !!
|
||||||
|
{
|
||||||
|
cout << "Error in AddElem: (" << ii << "," << jj << ") ["
|
||||||
|
<< ial[0] << "," << ial[1] << "," << ial[2] << "]\n";
|
||||||
|
assert(!not_found);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
sk[ip - 1] += ske[i][j];
|
||||||
|
}
|
||||||
|
f[ii] += fe[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// #####################################################################
|
||||||
|
|
||||||
|
BisectInterpolation::BisectInterpolation()
|
||||||
|
: Matrix( 0, 0 ), _iv(), _vv()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BisectInterpolation::BisectInterpolation(std::vector<int> const & fathers)
|
||||||
|
: Matrix( static_cast<int>(fathers.size())/2, 1+*max_element(fathers.cbegin(),fathers.cend()) ),
|
||||||
|
_iv(fathers), _vv(fathers.size(),0.5)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BisectInterpolation::~BisectInterpolation()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void BisectInterpolation::GetDiag(vector<double> &d) const
|
||||||
|
{
|
||||||
|
assert( Nrows()==static_cast<int>(d.size()) );
|
||||||
|
|
||||||
|
for (int k=0; k<Nrows(); ++k)
|
||||||
|
{
|
||||||
|
if ( _iv[2*k]==_iv[2*k+1] )
|
||||||
|
{
|
||||||
|
d[k] = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d[k] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BisectInterpolation::Mult(vector<double> &wf, vector<double> const &uc) const
|
||||||
|
{
|
||||||
|
assert( Nrows()==static_cast<int>(wf.size()) );
|
||||||
|
assert( Ncols()==static_cast<int>(uc.size()) );
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int k=0; k<Nrows(); ++k)
|
||||||
|
{
|
||||||
|
wf[k] = _vv[2*k]*uc[_iv[2*k]] + _vv[2*k+1]*uc[_iv[2*k+1]];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//void BisectInterpolation::MultT(vector<double> const &wf, vector<double> &uc) const
|
||||||
|
//{
|
||||||
|
//assert( Nrows()==static_cast<int>(wf.size()) );
|
||||||
|
//assert( Ncols()==static_cast<int>(uc.size()) );
|
||||||
|
//// GH: atomic slows down the code ==> use different storage for MultT operation (CRS-matrix?)
|
||||||
|
////#pragma omp parallel for
|
||||||
|
//for (int k=0; k<Ncols(); ++k) uc[k] = 0.0;
|
||||||
|
//#pragma omp parallel for
|
||||||
|
//for (int k=0; k<Nrows(); ++k)
|
||||||
|
//{
|
||||||
|
//#pragma omp atomic
|
||||||
|
//uc[_iv[2*k] ] += _vv[2*k ]*wf[k];
|
||||||
|
//#pragma omp atomic
|
||||||
|
//uc[_iv[2*k+1]] += _vv[2*k+1]*wf[k];
|
||||||
|
//}
|
||||||
|
//return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
void BisectInterpolation::MultT(vector<double> const &wf, vector<double> &uc) const
|
||||||
|
{
|
||||||
|
assert( Nrows()==static_cast<int>(wf.size()) );
|
||||||
|
assert( Ncols()==static_cast<int>(uc.size()) );
|
||||||
|
// GH: atomic slows down the code ==> use different storage for MultT operation (CRS-matrix?)
|
||||||
|
//#pragma omp parallel for
|
||||||
|
for (int k=0; k<Ncols(); ++k) uc[k] = 0.0;
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int k=0; k<Nrows(); ++k)
|
||||||
|
{
|
||||||
|
if (_iv[2*k]!=_iv[2*k+1])
|
||||||
|
{
|
||||||
|
#pragma omp atomic
|
||||||
|
uc[_iv[2*k] ] += _vv[2*k ]*wf[k];
|
||||||
|
#pragma omp atomic
|
||||||
|
uc[_iv[2*k+1]] += _vv[2*k+1]*wf[k];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#pragma omp atomic
|
||||||
|
uc[_iv[2*k] ] += 2.0*_vv[2*k ]*wf[k]; // uses a property of class BisectInterpolation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BisectInterpolation::Defect(vector<double> &w,
|
||||||
|
vector<double> const &f, vector<double> const &u) const
|
||||||
|
{
|
||||||
|
assert( Nrows()==static_cast<int>(w.size()) );
|
||||||
|
assert( Ncols()==static_cast<int>(u.size()) );
|
||||||
|
assert( w.size()==f.size() );
|
||||||
|
|
||||||
|
for (int k=0; k<Nrows(); ++k)
|
||||||
|
{
|
||||||
|
w[k] = f[k] - _vv[2*k]*u[_iv[2*k]] + _vv[2*k+1]*u[_iv[2*k+1]];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BisectInterpolation::Debug() const
|
||||||
|
{
|
||||||
|
for (int k=0; k<Nrows(); ++k)
|
||||||
|
{
|
||||||
|
cout << k << " : fathers(" << _iv[2*k] << "," << _iv[2*k+1] << ") ";
|
||||||
|
cout << "weights(" << _vv[2*k] << "," << _vv[2*k+1] << endl;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BisectInterpolation::fetch(int row, int col) const
|
||||||
|
{
|
||||||
|
int idx(-1);
|
||||||
|
if (_iv[2*row ] == col) idx = 2*row;
|
||||||
|
if (_iv[2*row+1] == col) idx = 2*row+1;
|
||||||
|
assert(idx>=0);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #####################################################################
|
||||||
|
|
||||||
|
BisectIntDirichlet::BisectIntDirichlet(std::vector<int> const & fathers, std::vector<int> const & idxc_dir)
|
||||||
|
: BisectInterpolation(fathers)
|
||||||
|
{
|
||||||
|
vector<bool> bdir(Ncols(), false); // Indicator for Dirichlet coarse nodes
|
||||||
|
for (size_t kc=0; kc<idxc_dir.size(); ++kc)
|
||||||
|
{
|
||||||
|
bdir.at(idxc_dir[kc]) = true; // Mark Dirichlet node from coarse mesh
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j=0; j<_iv.size(); ++j)
|
||||||
|
{
|
||||||
|
if ( bdir.at(_iv[j]) ) _vv[j] = 0.0; // set weight to zero iff (at least) one father is Dirichlet node
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BisectIntDirichlet::~BisectIntDirichlet()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// #####################################################################
|
||||||
|
|
||||||
|
void DefectRestrict(CRS_Matrix const & SK, BisectInterpolation const& P,
|
||||||
|
vector<double> &fc, vector<double> &ff, vector<double> &uf)
|
||||||
|
{
|
||||||
|
assert( P.Nrows()==static_cast<int>(ff.size()) );
|
||||||
|
assert( P.Ncols()==static_cast<int>(fc.size()) );
|
||||||
|
assert( ff.size()==uf.size() );
|
||||||
|
assert( P.Nrows()==SK.Nrows() );
|
||||||
|
|
||||||
|
//#pragma omp parallel for
|
||||||
|
for (int k=0; k<P.Ncols(); ++k) fc[k] = 0.0;
|
||||||
|
|
||||||
|
// GH: atomic slows down the code ==> use different storage for MultT operation (CRS-matrix?)
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int row = 0; row < SK._nrows; ++row)
|
||||||
|
{
|
||||||
|
double wi = ff[row];
|
||||||
|
for (int ij = SK._id[row]; ij < SK._id[row + 1]; ++ij)
|
||||||
|
{
|
||||||
|
wi -= SK._sk[ij] * uf[ SK._ik[ij] ];
|
||||||
|
}
|
||||||
|
|
||||||
|
const int i1=P._iv[2*row];
|
||||||
|
const int i2=P._iv[2*row+1];
|
||||||
|
if (i1!=i2)
|
||||||
|
{
|
||||||
|
#pragma omp atomic
|
||||||
|
fc[i1] += P._vv[2*row ]*wi;
|
||||||
|
#pragma omp atomic
|
||||||
|
fc[i2] += P._vv[2*row +1]*wi;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#pragma omp atomic
|
||||||
|
fc[i1] += 2.0*P._vv[2*row ]*wi; // uses a property of class BisectInterpolation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
545
sheet7/jacobi.template/getmatrix.h
Normal file
545
sheet7/jacobi.template/getmatrix.h
Normal file
|
|
@ -0,0 +1,545 @@
|
||||||
|
#ifndef GETMATRIX_FILE
|
||||||
|
#define GETMATRIX_FILE
|
||||||
|
|
||||||
|
#include "geom.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <vector>
|
||||||
|
// #####################################################################
|
||||||
|
/**
|
||||||
|
* Abstract matrix class.
|
||||||
|
*/
|
||||||
|
class Matrix
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor for abstract matrix class.
|
||||||
|
*
|
||||||
|
* No memory is allocated.
|
||||||
|
*
|
||||||
|
* @param[in] nrows number of matrix rows.
|
||||||
|
* @param[in] ncols number of matrix columns.
|
||||||
|
*/
|
||||||
|
Matrix(int nrows, int ncols);
|
||||||
|
//Matrix();
|
||||||
|
|
||||||
|
Matrix(Matrix const &) = default;
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*
|
||||||
|
* No memory is allocated.
|
||||||
|
*/
|
||||||
|
virtual ~Matrix();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the matrix is a square matrix.
|
||||||
|
*
|
||||||
|
* @return True iff square matrix.
|
||||||
|
*/
|
||||||
|
bool isSquare() const
|
||||||
|
{
|
||||||
|
return _nrows == _ncols;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of rows in matrix.
|
||||||
|
* @return number of rows.
|
||||||
|
*/
|
||||||
|
int Nrows() const
|
||||||
|
{
|
||||||
|
return _nrows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of columns in matrix.
|
||||||
|
* @return number of columns.
|
||||||
|
*/
|
||||||
|
int Ncols() const
|
||||||
|
{
|
||||||
|
return _ncols;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the matrix entries.
|
||||||
|
*/
|
||||||
|
virtual void Debug() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the diagonal elements of an inherited matrix.
|
||||||
|
*
|
||||||
|
* @param[in,out] d (prellocated) vector of diagonal elements
|
||||||
|
*/
|
||||||
|
virtual void GetDiag(std::vector<double> &d) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the diagonal elements of the matrix.
|
||||||
|
*
|
||||||
|
* @return d vector of diagonal elements
|
||||||
|
*/
|
||||||
|
std::vector<double> const &GetDiag() const
|
||||||
|
{
|
||||||
|
if ( 0 == _dd.size() ) // GH: better? Nrows()>static_cast<int>(_dd.size())
|
||||||
|
{
|
||||||
|
_dd.resize(Nrows());
|
||||||
|
this->GetDiag(_dd);
|
||||||
|
}
|
||||||
|
assert( Nrows() == static_cast<int>(_dd.size()) );
|
||||||
|
return _dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the matrix-vector product w := K*u.
|
||||||
|
*
|
||||||
|
* @param[in,out] w resulting vector (preallocated)
|
||||||
|
* @param[in] u vector
|
||||||
|
*/
|
||||||
|
virtual void Mult(std::vector<double> &w, std::vector<double> const &u) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the defect/residuum w := f - K*u.
|
||||||
|
*
|
||||||
|
* @param[in,out] w resulting vector (preallocated)
|
||||||
|
* @param[in] f load vector
|
||||||
|
* @param[in] u vector
|
||||||
|
*/
|
||||||
|
virtual void Defect(
|
||||||
|
std::vector<double> &w,
|
||||||
|
std::vector<double> const &f, std::vector<double> const &u) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds in a CRS matrix the access index for an entry at row @p row and column @p col.
|
||||||
|
*
|
||||||
|
* @param[in] row row index
|
||||||
|
* @param[in] col column index
|
||||||
|
* @return index for element (@p row, @p col). If no appropriate entry exists then -1 will be returned.
|
||||||
|
*
|
||||||
|
* @warning assert() stops the function in case that matrix element (@p row, @p col) doesn't exist.
|
||||||
|
*/
|
||||||
|
virtual int fetch(int row, int col) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int _nrows; //!< number of rows in matrix
|
||||||
|
int _ncols; //!< number of columns in matrix
|
||||||
|
mutable std::vector<double> _dd; //!< diagonal matrix elements
|
||||||
|
};
|
||||||
|
|
||||||
|
// #####################################################################
|
||||||
|
class BisectInterpolation; // class forward declaration
|
||||||
|
/**
|
||||||
|
* Matrix in CRS format (compressed row storage; also named CSR),
|
||||||
|
* see an <a href="https://en.wikipedia.org/wiki/Sparse_matrix">introduction</a>.
|
||||||
|
*/
|
||||||
|
class CRS_Matrix: public Matrix
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CRS_Matrix();
|
||||||
|
|
||||||
|
CRS_Matrix(CRS_Matrix const &) = default;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~CRS_Matrix() override;
|
||||||
|
/**
|
||||||
|
* Extracts the diagonal elements of the sparse matrix.
|
||||||
|
*
|
||||||
|
* @param[in,out] d (prellocated) vector of diagonal elements
|
||||||
|
*/
|
||||||
|
void GetDiag(std::vector<double> &d) const override;
|
||||||
|
///**
|
||||||
|
//* Extracts the diagonal elements of the sparse matrix.
|
||||||
|
//*
|
||||||
|
//* @return d vector of diagonal elements
|
||||||
|
//*/
|
||||||
|
//std::vector<double> const & GetDiag() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the matrix-vector product w := K*u.
|
||||||
|
*
|
||||||
|
* @param[in,out] w resulting vector (preallocated)
|
||||||
|
* @param[in] u vector
|
||||||
|
*/
|
||||||
|
void Mult(std::vector<double> &w, std::vector<double> const &u) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the defect/residuum w := f - K*u.
|
||||||
|
*
|
||||||
|
* @param[in,out] w resulting vector (preallocated)
|
||||||
|
* @param[in] f load vector
|
||||||
|
* @param[in] u vector
|
||||||
|
*/
|
||||||
|
void Defect(std::vector<double> &w,
|
||||||
|
std::vector<double> const &f, std::vector<double> const &u) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the matrix entries.
|
||||||
|
*/
|
||||||
|
void Debug() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds in a CRS matrix the access index for an entry at row @p row and column @p col.
|
||||||
|
*
|
||||||
|
* @param[in] row row index
|
||||||
|
* @param[in] col column index
|
||||||
|
* @return index for element (@p row, @p col). If no appropriate entry exists then -1 will be returned.
|
||||||
|
*
|
||||||
|
* @warning assert() stops the function in case that matrix element (@p row, @p col) doesn't exist.
|
||||||
|
*/
|
||||||
|
int fetch(int row, int col) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare @p this CRS matrix with an external CRS matrix stored in C-Style.
|
||||||
|
*
|
||||||
|
* The method prints statements on differences found.
|
||||||
|
*
|
||||||
|
* @param[in] nnode row number of external matrix
|
||||||
|
* @param[in] id start indices of matrix rows of external matrix
|
||||||
|
* @param[in] ik column indices of external matrix
|
||||||
|
* @param[in] sk non-zero values of external matrix
|
||||||
|
*
|
||||||
|
* @return true iff all data are identical.
|
||||||
|
*/
|
||||||
|
bool Compare2Old(int nnode, int const id[], int const ik[], double const sk[]) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the defect and projects it to the next coarser level @f$ f_C := P^T \cdot (f_F - SK\cdot u_F) @f$.
|
||||||
|
*
|
||||||
|
* @param[in] SK matrix on fine mesh
|
||||||
|
* @param[in] P prolongation operator
|
||||||
|
* @param[in,out] fc resulting coarse mesh vector (preallocated)
|
||||||
|
* @param[in] ff r.h.s. on fine mesh
|
||||||
|
* @param[in] uf status vector on fine mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
friend void DefectRestrict(CRS_Matrix const &SK, BisectInterpolation const &P,
|
||||||
|
std::vector<double> &fc, std::vector<double> &ff, std::vector<double> &uf);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//int _nrows; //!< number of rows in matrix
|
||||||
|
//int _ncols; //!< number of columns in matrix
|
||||||
|
int _nnz; //!< number of non-zero entries
|
||||||
|
std::vector<int> _id; //!< start indices of matrix rows
|
||||||
|
std::vector<int> _ik; //!< column indices
|
||||||
|
std::vector<double> _sk; //!< non-zero values
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FEM Matrix in CRS format (compressed row storage; also named CSR),
|
||||||
|
* see an <a href="https://en.wikipedia.org/wiki/Sparse_matrix">introduction</a>.
|
||||||
|
*/
|
||||||
|
class FEM_Matrix: public CRS_Matrix
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Initializes the CRS matrix structure from the given discretization in @p mesh.
|
||||||
|
*
|
||||||
|
* The sparse matrix pattern is generated but the values are 0.
|
||||||
|
*
|
||||||
|
* @param[in] mesh given discretization
|
||||||
|
*
|
||||||
|
* @warning A reference to the discretization @p mesh is stored inside this class.
|
||||||
|
* Therefore, changing @p mesh outside requires also
|
||||||
|
* to call method @p Derive_Matrix_Pattern explicitly.
|
||||||
|
*
|
||||||
|
* @see Derive_Matrix_Pattern
|
||||||
|
*/
|
||||||
|
explicit FEM_Matrix(Mesh const &mesh);
|
||||||
|
|
||||||
|
FEM_Matrix(FEM_Matrix const &) = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~FEM_Matrix() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the sparse matrix pattern and overwrites the existing pattern.
|
||||||
|
*
|
||||||
|
* The sparse matrix pattern is generated but the values are 0.
|
||||||
|
*/
|
||||||
|
void Derive_Matrix_Pattern()
|
||||||
|
{
|
||||||
|
//Derive_Matrix_Pattern_slow();
|
||||||
|
Derive_Matrix_Pattern_fast();
|
||||||
|
}
|
||||||
|
void Derive_Matrix_Pattern_fast();
|
||||||
|
void Derive_Matrix_Pattern_slow();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the entries of f.e. stiffness matrix and load/rhs vector @p f for the Laplace operator in 2D.
|
||||||
|
* No memory is allocated.
|
||||||
|
*
|
||||||
|
* @param[in,out] f (preallocated) rhs/load vector
|
||||||
|
*/
|
||||||
|
void CalculateLaplace(std::vector<double> &f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies Dirichlet boundary conditions to stiffness matrix and to load vector @p f.
|
||||||
|
* The <a href="https://www.jstor.org/stable/2005611?seq=1#metadata_info_tab_contents">penalty method</a>
|
||||||
|
* is used for incorporating the given values @p u.
|
||||||
|
*
|
||||||
|
* @param[in] u (global) vector with Dirichlet data
|
||||||
|
* @param[in,out] f load vector
|
||||||
|
*/
|
||||||
|
void ApplyDirichletBC(std::vector<double> const &u, std::vector<double> &f);
|
||||||
|
|
||||||
|
///**
|
||||||
|
//* Extracts the diagonal elements of the sparse matrix.
|
||||||
|
//*
|
||||||
|
//* @param[in,out] d (prellocated) vector of diagonal elements
|
||||||
|
//*/
|
||||||
|
//void GetDiag(std::vector<double> &d) const; // override in MPI parallel
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the element stiffness matrix @p ske and the element load vector @p fe
|
||||||
|
* of one triangular element with linear shape functions to the appropriate positions in
|
||||||
|
* the stiffness matrix, stored as CSR matrix K(@p sk,@p id, @p ik).
|
||||||
|
*
|
||||||
|
* @param[in] ial node indices of the three element vertices
|
||||||
|
* @param[in] ske element stiffness matrix
|
||||||
|
* @param[in] fe element load vector
|
||||||
|
* @param[in,out] f distributed local vector storing the right hand side
|
||||||
|
*
|
||||||
|
* @warning Algorithm assumes linear triangular elements (ndof_e==3).
|
||||||
|
*/
|
||||||
|
void AddElem_3(int const ial[3], double const ske[3][3], double const fe[3], std::vector<double> &f);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mesh const &_mesh; //!< reference to discretization
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///**
|
||||||
|
//* Prolongation matrix in CRS format (compressed row storage; also named CSR),
|
||||||
|
//* see an <a href="https://en.wikipedia.org/wiki/Sparse_matrix">introduction</a>.
|
||||||
|
//*
|
||||||
|
//* The prolongation is applied for each node from the coarse mesh to the fine mesh and
|
||||||
|
//* is derived only geometrically (no operator weighted prolongation).
|
||||||
|
//*/
|
||||||
|
//class Prolongation: public CRS_Matrix
|
||||||
|
//{
|
||||||
|
//public:
|
||||||
|
///**
|
||||||
|
//* Intializes the CRS matrix structure from the given discetization in @p mesh.
|
||||||
|
//*
|
||||||
|
//* The sparse matrix pattern is generated but the values are 0.
|
||||||
|
//*
|
||||||
|
//* @param[in] cmesh coarse mesh
|
||||||
|
//* @param[in] fmesh fine mesh
|
||||||
|
//*
|
||||||
|
//* @warning A reference to the discretizations @p fmesh @p cmesh are stored inside this class.
|
||||||
|
//* Therefore, changing these meshes outside requires also
|
||||||
|
//* to call method @p Derive_Matrix_Pattern explicitely.
|
||||||
|
//*
|
||||||
|
//* @see Derive_Matrix_Pattern
|
||||||
|
//*/
|
||||||
|
//Prolongation(Mesh const & cmesh, Mesh const & fmesh);
|
||||||
|
|
||||||
|
///**
|
||||||
|
//* Destructor.
|
||||||
|
//*/
|
||||||
|
//~Prolongation() override
|
||||||
|
//{}
|
||||||
|
|
||||||
|
///**
|
||||||
|
//* Generates the sparse matrix pattern and overwrites the existing pattern.
|
||||||
|
//*
|
||||||
|
//* The sparse matrix pattern is generated but the values are 0.
|
||||||
|
//*/
|
||||||
|
//void Derive_Matrix_Pattern() override;
|
||||||
|
|
||||||
|
//private:
|
||||||
|
//Mesh const & _cmesh; //!< reference to coarse discretization
|
||||||
|
//Mesh const & _fmesh; //!< reference to fine discretization
|
||||||
|
//};
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpolation matrix for prolongation coarse mesh (C) to a fine mesh (F)
|
||||||
|
* generated by bisecting edges.
|
||||||
|
*
|
||||||
|
* All interpolation weights are 0.5 (injection points contribute twice).
|
||||||
|
*/
|
||||||
|
class BisectInterpolation: public Matrix
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Generates the interpolation matrix for prolongation coarse mesh to a fine mesh
|
||||||
|
* generated by bisecting edges.
|
||||||
|
* The interpolation weights are all 0.5.
|
||||||
|
*
|
||||||
|
* @param[in] fathers vector[nnodes][2] containing
|
||||||
|
* the two coarse grid fathers of a fine grid vertex
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
explicit BisectInterpolation(std::vector<int> const &fathers);
|
||||||
|
BisectInterpolation();
|
||||||
|
|
||||||
|
BisectInterpolation(BisectInterpolation const &) = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~BisectInterpolation() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the diagonal elements of the matrix.
|
||||||
|
*
|
||||||
|
* @param[in,out] d (prellocated) vector of diagonal elements
|
||||||
|
*/
|
||||||
|
void GetDiag(std::vector<double> &d) const override;
|
||||||
|
///**
|
||||||
|
//* Extracts the diagonal elements of the sparse matrix.
|
||||||
|
//*
|
||||||
|
//* @return d vector of diagonal elements
|
||||||
|
//*/
|
||||||
|
//std::vector<double> const & GetDiag() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the prolongation @f$ w_F := P*u_C @f$.
|
||||||
|
*
|
||||||
|
* @param[in,out] wf resulting fine vector (preallocated)
|
||||||
|
* @param[in] uc coarse vector
|
||||||
|
*/
|
||||||
|
void Mult(std::vector<double> &wf, std::vector<double> const &uc) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the restriction @f$ u_C := P^T*w_F @f$.
|
||||||
|
*
|
||||||
|
* @param[in] wf fine vector
|
||||||
|
* @param[in,out] uc resulting coarse vector (preallocated)
|
||||||
|
*/
|
||||||
|
void MultT(std::vector<double> const &wf, std::vector<double> &uc) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the defect/residuum w := f - P*u.
|
||||||
|
*
|
||||||
|
* @param[in,out] w resulting vector (preallocated)
|
||||||
|
* @param[in] f load vector
|
||||||
|
* @param[in] u coarse vector
|
||||||
|
*/
|
||||||
|
void Defect(std::vector<double> &w,
|
||||||
|
std::vector<double> const &f, std::vector<double> const &u) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the matrix entries.
|
||||||
|
*/
|
||||||
|
void Debug() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds in this matrix the access index for an entry at row @p row and column @p col.
|
||||||
|
*
|
||||||
|
* @param[in] row row index
|
||||||
|
* @param[in] col column index
|
||||||
|
* @return index for element (@p row, @p col). If no appropriate entry exists then -1 will be returned.
|
||||||
|
*
|
||||||
|
* @warning assert() stops the function in case that matrix element (@p row, @p col) doesn't exist.
|
||||||
|
*/
|
||||||
|
int fetch(int row, int col) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the defect and projects it to the next coarser level @f$ f_C := P^T \cdot (f_F - SK\cdot u_F) @f$.
|
||||||
|
*
|
||||||
|
* @param[in] SK matrix on fine mesh
|
||||||
|
* @param[in] P prolongation operator
|
||||||
|
* @param[in,out] fc resulting coarse mesh vector (preallocated)
|
||||||
|
* @param[in] ff r.h.s. on fine mesh
|
||||||
|
* @param[in] uf status vector on fine mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
friend void DefectRestrict(CRS_Matrix const &SK, BisectInterpolation const &P,
|
||||||
|
std::vector<double> &fc, std::vector<double> &ff, std::vector<double> &uf);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<int> _iv; //!< fathers[nnode][2] of fine grid nodes, double entries denote injection points
|
||||||
|
std::vector<double> _vv; //!< weights[nnode][2] of fathers for grid nodes
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpolation matrix for prolongation from coarse mesh (C)) to a fine mesh (F)
|
||||||
|
* generated by bisecting edges.
|
||||||
|
*
|
||||||
|
* We take into account that values at Dirichlet nodes have to be preserved, i.e.,
|
||||||
|
* @f$ w_F = P \cdot I_D \cdot w_C @f$ and @f$ d_C = I_D \cdot P^T \cdot d_F@f$
|
||||||
|
* with @f$ I_D @f$ as @f$ n_C \times n_C @f$ diagonal matrix and entries
|
||||||
|
* @f$ I_{D(j,j)} := \left\{{\begin{array}{l@{\qquad}l} 0 & x_{j}\;\; \textrm{is Dirichlet node} \\ 1 & \textrm{else} \end{array}}\right. @f$
|
||||||
|
*
|
||||||
|
* Interpolation weights are eighter 0.5 or 0.0 in case of coarse Dirichlet nodes
|
||||||
|
* (injection points contribute twice),
|
||||||
|
* Sets weight to zero iff (at least) one father nodes is a Dirichlet node.
|
||||||
|
*/
|
||||||
|
class BisectIntDirichlet: public BisectInterpolation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
BisectIntDirichlet()
|
||||||
|
: BisectInterpolation()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs interpolation from father-@p row and column @p col.
|
||||||
|
*
|
||||||
|
* @param[in] fathers two father nodes from each fine node [nnode_f*2].
|
||||||
|
* @param[in] idxc_dir vector containing the indices of coarse mesh Dirichlet nodes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BisectIntDirichlet(std::vector<int> const &fathers, std::vector<int> const &idxc_dir);
|
||||||
|
|
||||||
|
BisectIntDirichlet(BisectIntDirichlet const &) = default;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~BisectIntDirichlet() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the element stiffness matrix @p ske and the element load vector @p fe
|
||||||
|
* of one triangular element with linear shape functions.
|
||||||
|
* @param[in] ial node indices of the three element vertices
|
||||||
|
* @param[in] xc vector of node coordinates with x(2*k,2*k+1) as coordinates of node k
|
||||||
|
* @param[out] ske element stiffness matrix
|
||||||
|
* @param[out] fe element load vector
|
||||||
|
*/
|
||||||
|
void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the element stiffness matrix @p ske and the element load vector @p fe
|
||||||
|
* of one triangular element with linear shape functions to the appropriate positions in
|
||||||
|
* the symmetric stiffness matrix, stored as CSR matrix K(@p sk,@p id, @p ik)
|
||||||
|
*
|
||||||
|
* @param[in] ial node indices of the three element vertices
|
||||||
|
* @param[in] ske element stiffness matrix
|
||||||
|
* @param[in] fe element load vector
|
||||||
|
* @param[out] sk vector non-zero entries of CSR matrix
|
||||||
|
* @param[in] id index vector containing the first entry in a CSR row
|
||||||
|
* @param[in] ik column index vector of CSR matrix
|
||||||
|
* @param[out] f distributed local vector storing the right hand side
|
||||||
|
*
|
||||||
|
* @warning Algorithm requires indices in connectivity @p ial in ascending order.
|
||||||
|
* Currently deprecated.
|
||||||
|
*/
|
||||||
|
void AddElem(int const ial[3], double const ske[3][3], double const fe[3],
|
||||||
|
int const id[], int const ik[], double sk[], double f[]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
235
sheet7/jacobi.template/jacsolve.cpp
Normal file
235
sheet7/jacobi.template/jacsolve.cpp
Normal file
|
|
@ -0,0 +1,235 @@
|
||||||
|
#include "vdop.h"
|
||||||
|
#include "geom.h"
|
||||||
|
#include "getmatrix.h"
|
||||||
|
#include "jacsolve.h"
|
||||||
|
#include "userset.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// #####################################################################
|
||||||
|
// ParMesh const & mesh,
|
||||||
|
void JacobiSolve(CRS_Matrix const &SK, vector<double> const &f, vector<double> &u)
|
||||||
|
{
|
||||||
|
const double omega = 1.0;
|
||||||
|
const int maxiter = 1000;
|
||||||
|
const double tol = 1e-6, // tolerance
|
||||||
|
tol2 = tol * tol; // tolerance^2
|
||||||
|
|
||||||
|
int nrows = SK.Nrows(); // number of rows == number of columns
|
||||||
|
assert( nrows == static_cast<int>(f.size()) && f.size() == u.size() );
|
||||||
|
|
||||||
|
cout << endl << " Start Jacobi solver for " << nrows << " d.o.f.s" << endl;
|
||||||
|
// Choose initial guess
|
||||||
|
for (int k = 0; k < nrows; ++k) {
|
||||||
|
u[k] = 0.0; // u := 0
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<double> dd(nrows); // matrix diagonal
|
||||||
|
vector<double> r(nrows); // residual
|
||||||
|
vector<double> w(nrows); // correction
|
||||||
|
|
||||||
|
SK.GetDiag(dd); // dd := diag(K)
|
||||||
|
////DebugVector(dd);{int ijk; cin >> ijk;}
|
||||||
|
|
||||||
|
// Initial sweep
|
||||||
|
SK.Defect(r, f, u); // r := f - K*u
|
||||||
|
|
||||||
|
vddiv(w, r, dd); // w := D^{-1}*r
|
||||||
|
const double sigma0 = dscapr(w, r); // s0 := <w,r>
|
||||||
|
|
||||||
|
// Iteration sweeps
|
||||||
|
int iter = 0;
|
||||||
|
double sigma = sigma0;
|
||||||
|
while ( sigma > tol2 * sigma0 && maxiter > iter) // relative error
|
||||||
|
//while ( sigma > tol2 && maxiter > iter) // absolute error
|
||||||
|
{
|
||||||
|
++iter;
|
||||||
|
vdaxpy(u, u, omega, w ); // u := u + om*w
|
||||||
|
SK.Defect(r, f, u); // r := f - K*u
|
||||||
|
vddiv(w, r, dd); // w := D^{-1}*r
|
||||||
|
sigma = dscapr(w, r); // s0 := <w,r>
|
||||||
|
// cout << "Iteration " << iter << " : " << sqrt(sigma/sigma0) << endl;
|
||||||
|
}
|
||||||
|
cout << "aver. Jacobi rate : " << exp(log(sqrt(sigma / sigma0)) / iter) << " (" << iter << " iter)" << endl;
|
||||||
|
cout << "final error: " << sqrt(sigma / sigma0) << " (rel) " << sqrt(sigma) << " (abs)\n";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void JacobiSmoother(Matrix const &SK, std::vector<double> const &f, std::vector<double> &u,
|
||||||
|
std::vector<double> &r, int nsmooth, double const omega, bool zero)
|
||||||
|
{
|
||||||
|
// ToDO: ensure compatible dimensions
|
||||||
|
|
||||||
|
int const nnodes = static_cast<int>(u.size());
|
||||||
|
if (zero) { // assumes initial solution is zero
|
||||||
|
DiagPrecond(SK, f, u, omega);
|
||||||
|
--nsmooth; // first smoothing sweep done
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const &D = SK.GetDiag(); // accumulated diagonal of matrix @p SK.
|
||||||
|
for (int ns = 1; ns <= nsmooth; ++ns) {
|
||||||
|
SK.Defect(r, f, u); // r := f - K*u
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int k = 0; k < nnodes; ++k) {
|
||||||
|
// u := u + om*D^{-1}*r
|
||||||
|
u[k] = u[k] + omega * r[k] / D[k]; // MPI: distributed to accumulated vector needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiagPrecond(Matrix const &SK, std::vector<double> const &r, std::vector<double> &w,
|
||||||
|
double const omega)
|
||||||
|
{
|
||||||
|
// ToDO: ensure compatible dimensions
|
||||||
|
auto const &D = SK.GetDiag(); // accumulated diagonal of matrix @p SK.
|
||||||
|
int const nnodes = static_cast<int>(w.size());
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int k = 0; k < nnodes; ++k) {
|
||||||
|
w[k] = omega * r[k] / D[k]; // MPI: distributed to accumulated vector needed
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Multigrid::Multigrid(Mesh const &cmesh, int const nlevel)
|
||||||
|
: _meshes(cmesh, nlevel),
|
||||||
|
_SK(), _u(_meshes.size()), _f(_meshes.size()), _d(_meshes.size()), _w(_meshes.size()),
|
||||||
|
_Pc2f()
|
||||||
|
{
|
||||||
|
cout << "\n........................ in Multigrid::Multigrid ..................\n";
|
||||||
|
// Allocate Memory for matrices/vectors on all levels
|
||||||
|
for (size_t lev = 0; lev < Nlevels(); ++lev) {
|
||||||
|
_SK.push_back( FEM_Matrix(_meshes[lev]) ); // CRS matrix
|
||||||
|
const auto nn = _SK[lev].Nrows();
|
||||||
|
_u[lev].resize(nn);
|
||||||
|
_f[lev].resize(nn);
|
||||||
|
_d[lev].resize(nn);
|
||||||
|
_w[lev].resize(nn);
|
||||||
|
auto vv = _meshes[lev].GetFathersOfVertices();
|
||||||
|
cout << vv.size() << endl;
|
||||||
|
}
|
||||||
|
// Intergrid transfer operators
|
||||||
|
//cout << "\n........................ in Multigrid::Multigrid Prolongation ..................\n";
|
||||||
|
//_Pc2f.push_back( BisectInterpolation(vector<int>(0)) ); // no prolongation to coarsest grid
|
||||||
|
_Pc2f.push_back( BisectIntDirichlet() ); // no prolongation to coarsest grid
|
||||||
|
for (size_t lev = 1; lev < Nlevels(); ++lev) {
|
||||||
|
//cout << lev << endl;
|
||||||
|
//cout << _meshes[lev].GetFathersOfVertices () << endl;
|
||||||
|
_Pc2f.push_back( BisectIntDirichlet( _meshes[lev].GetFathersOfVertices (), _meshes[lev-1].Index_DirichletNodes () ) );
|
||||||
|
//cout << _Pc2f.back().Nrows() << " " << _Pc2f.back().Ncols() << endl;
|
||||||
|
}
|
||||||
|
cout << "\n..........................................\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
Multigrid::~Multigrid()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Multigrid::DefineOperators()
|
||||||
|
{
|
||||||
|
for (size_t lev = 0; lev < Nlevels(); ++lev) {
|
||||||
|
DefineOperator(lev);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GH: Hack
|
||||||
|
void Multigrid::DefineOperator(size_t lev)
|
||||||
|
{
|
||||||
|
_SK[lev].CalculateLaplace(_f[lev]); // fNice() in userset.h
|
||||||
|
|
||||||
|
if (lev == Nlevels() - 1) { // fine mesh
|
||||||
|
_meshes[lev].SetValues(_u[lev], [](double x, double y) -> double
|
||||||
|
{ return x *x * std::sin(2.5 * M_PI * y); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_meshes[lev].SetValues(_u[lev], f_zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
_SK[lev].ApplyDirichletBC(_u[lev], _f[lev]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Multigrid::JacobiSolve(size_t lev)
|
||||||
|
{
|
||||||
|
assert(lev < Nlevels());
|
||||||
|
::JacobiSolve(_SK[lev], _f[lev], _u[lev]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Multigrid::MG_Step(size_t lev, int const pre_smooth, bool const bzero, int nu)
|
||||||
|
{
|
||||||
|
assert(lev < Nlevels());
|
||||||
|
int const post_smooth = pre_smooth;
|
||||||
|
|
||||||
|
if (lev == 0) { // coarse level
|
||||||
|
JacobiSmoother(_SK[lev], _f[lev], _u[lev], _d[lev], 100, 1.0, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JacobiSmoother(_SK[lev], _f[lev], _u[lev], _d[lev], pre_smooth, 0.85, bzero);
|
||||||
|
|
||||||
|
if (nu > 0) {
|
||||||
|
|
||||||
|
_SK[lev].Defect(_d[lev], _f[lev], _u[lev]); // d := f - K*u
|
||||||
|
_Pc2f[lev].MultT(_d[lev], _f[lev - 1]); // f_H := R*d
|
||||||
|
//DefectRestrict(_SK[lev], _Pc2f[lev], _f[lev - 1], _f[lev], _u[lev]); // f_H := R*(f - K*u)
|
||||||
|
|
||||||
|
//_meshes[lev-1].Visualize(_f[lev - 1]); // GH: Visualize: f_H should be 0 on Dirichlet B.C.
|
||||||
|
|
||||||
|
MG_Step(lev - 1, pre_smooth, true, nu); // solve K_H * u_H =f_H with u_H:=0
|
||||||
|
for (int k = 1; k < nu; ++k) {
|
||||||
|
// W-cycle
|
||||||
|
MG_Step(lev - 1, pre_smooth, false, nu); // solve K_H * u_H =f_H
|
||||||
|
}
|
||||||
|
|
||||||
|
_Pc2f[lev].Mult(_w[lev], _u[lev - 1]); // w := P*u_H
|
||||||
|
|
||||||
|
vdaxpy(_u[lev], _u[lev], 1.0, _w[lev] ); // u := u + tau*w
|
||||||
|
}
|
||||||
|
|
||||||
|
JacobiSmoother(_SK[lev], _f[lev], _u[lev], _d[lev], post_smooth, 0.85, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Multigrid::MG_Solve(int pre_smooth, double eps, int nu)
|
||||||
|
{
|
||||||
|
size_t lev=Nlevels()-1; // fine level
|
||||||
|
|
||||||
|
// start with zero guess
|
||||||
|
DiagPrecond(_SK[lev], _f[lev], _w[lev], 1.0); // w := D^{-1]*f
|
||||||
|
//double s0 = L2_scapr(_f[lev],_w[lev]); // s_0 := <f,w>
|
||||||
|
double s0 = dscapr(_f[lev],_w[lev]); // s_0 := <f,w>
|
||||||
|
double si;
|
||||||
|
|
||||||
|
bool bzero = true; // start with zero guess
|
||||||
|
int iter = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
MG_Step(lev, pre_smooth, bzero, nu);
|
||||||
|
bzero=false;
|
||||||
|
_SK[lev].Defect(_d[lev], _f[lev], _u[lev]); // d := f - K*u
|
||||||
|
DiagPrecond(_SK[lev], _d[lev], _w[lev], 1.0); // w := D^{-1]*d
|
||||||
|
//si = L2_scapr(_d[lev],_w[lev]); // s_i := <d,w>
|
||||||
|
si = dscapr(_d[lev],_w[lev]); // s_i := <d,w>
|
||||||
|
++iter;
|
||||||
|
} while (si>s0*eps*eps);
|
||||||
|
|
||||||
|
|
||||||
|
cout << "\nrel. error: " << sqrt(si/s0) << " ( " << iter << " iter.)" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
154
sheet7/jacobi.template/jacsolve.h
Normal file
154
sheet7/jacobi.template/jacsolve.h
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
#ifndef JACSOLVE_FILE
|
||||||
|
#define JACSOLVE_FILE
|
||||||
|
#include "geom.h"
|
||||||
|
#include "getmatrix.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves linear system of equations K @p u = @p f via the Jacobi iteration.
|
||||||
|
* We use a distributed symmetric CSR matrix @p SK and initial guess of the
|
||||||
|
* solution is set to 0.
|
||||||
|
* @param[in] SK CSR matrix
|
||||||
|
* @param[in] f distributed local vector storing the right hand side
|
||||||
|
* @param[out] u accumulated local vector storing the solution.
|
||||||
|
*/
|
||||||
|
void JacobiSolve(CRS_Matrix const &SK, std::vector<double> const &f, std::vector<double> &u);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves linear system of equations K @p u = @p f via the Jacobi iteration.
|
||||||
|
* We use a distributed symmetric CSR matrix @p SK and initial guess of the
|
||||||
|
* solution is set to 0.
|
||||||
|
*
|
||||||
|
* In each smoothing step: @f$ \widehat{u} := u + \omega D^{-1}\left({f-K*u}\right) @f$
|
||||||
|
*
|
||||||
|
* @param[in] SK CSR matrix
|
||||||
|
* @param[in] f distributed local vector storing the right hand side
|
||||||
|
* @param[out] u accumulated local vector storing the solution.
|
||||||
|
* @param[in,out] r auxiliary local vector.
|
||||||
|
* @param[in] nsmooth number of smoothing steps.
|
||||||
|
* @param[in] omega relaxation parameter.
|
||||||
|
* @param[in] zero initial solution @p u is assumed to be zero.
|
||||||
|
*/
|
||||||
|
void JacobiSmoother(Matrix const &SK, std::vector<double> const &f, std::vector<double> &u,
|
||||||
|
std::vector<double> & r, int nsmooth=1, double const omega=1.0, bool zero=false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Simple diagonale preconditioning.
|
||||||
|
*
|
||||||
|
* The residuum @p r scaled by the inverse diagonal of matríx @p SK results in the correction @p w.
|
||||||
|
*
|
||||||
|
* @f$ w := \omega D^{-1}*r @f$
|
||||||
|
*
|
||||||
|
* @param[in] SK matrix
|
||||||
|
* @param[in] r distributed local vector storing the residuum
|
||||||
|
* @param[out] w accumulated local vector storing the correction.
|
||||||
|
* @param[in] omega relaxation parameter.
|
||||||
|
*/
|
||||||
|
void DiagPrecond(Matrix const &SK, std::vector<double> const &r, std::vector<double> &w,
|
||||||
|
double const omega=1.0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The Multigrid hierarchy including meshes, vectors and matrices, prolongations is stored.
|
||||||
|
*/
|
||||||
|
class Multigrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Generates the mesh hierachy with @p nlevel meshes starting from coarse mesh @p cmesg .
|
||||||
|
*
|
||||||
|
* The refined meshes are generated by edge bisection.
|
||||||
|
* All memory is allocated but stiffness matrices are yet not calculated
|
||||||
|
*
|
||||||
|
* @param[in] cmesh initial coarse mesh
|
||||||
|
* @param[in] nlevel number of meshes in hierarchy, including the initial coarse mesh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Multigrid(Mesh const& cmesh, int nlevel);
|
||||||
|
|
||||||
|
Multigrid(Multigrid const&) = delete;
|
||||||
|
Multigrid& operator=(Multigrid const&) = delete;
|
||||||
|
|
||||||
|
~Multigrid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Number of meshes in hierarchy.
|
||||||
|
*/
|
||||||
|
size_t Nlevels() const
|
||||||
|
{return _meshes.size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Number of Unknowns.
|
||||||
|
*/
|
||||||
|
int Ndofs() const
|
||||||
|
{return _meshes[Nlevels()-1].Nnodes(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Meshes number @p lev .
|
||||||
|
*/
|
||||||
|
Mesh const& GetMesh(int lev) const
|
||||||
|
{ return _meshes[lev]; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Solution vector at level @p lev .
|
||||||
|
*/
|
||||||
|
std::vector<double> const& GetSolution(int lev) const
|
||||||
|
{ return _u.at(lev); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates PDE matrices for all levels.
|
||||||
|
*/
|
||||||
|
void DefineOperators();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates PDE matrix for level @p lev.
|
||||||
|
*
|
||||||
|
* @param[in] lev level in hierachy
|
||||||
|
*/
|
||||||
|
void DefineOperator(size_t lev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves the system of equations at level @p lev via Jacobi iterations
|
||||||
|
*
|
||||||
|
* @param[in] lev level in hierachy
|
||||||
|
*/
|
||||||
|
void JacobiSolve(size_t lev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peformes one multigrid step at level @p lev .
|
||||||
|
*
|
||||||
|
* @param[in] lev level in hierachy
|
||||||
|
* @param[in] pre_smooth number of pre/post-smoothing sweeps
|
||||||
|
* @param[in] bzero start with zero-vector as solution
|
||||||
|
* @param[in] nu defines the multigrid cycle (1/2 = V/W)
|
||||||
|
*/
|
||||||
|
void MG_Step(size_t lev, int pre_smooth=1, bool const bzero=false, int nu=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves the system of equations at finest level via multigrid
|
||||||
|
*
|
||||||
|
* @param[in] pre_smooth number of pre/post-smoothing sweeps
|
||||||
|
* @param[in] eps stopping criteria (relative error)
|
||||||
|
* @param[in] nu defines the multigrid cycle (1/2 = V/W)
|
||||||
|
*/
|
||||||
|
void MG_Solve(int pre_smooth=1, double eps=1e-6, int nu=1);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
gMesh_Hierarchy _meshes; //!< mesh hierarchy from coarse (level 0) to fine.
|
||||||
|
std::vector<FEM_Matrix> _SK; //!< Sparse matrix on each level.
|
||||||
|
std::vector<std::vector<double>> _u; //!< Solution vector on each level.
|
||||||
|
std::vector<std::vector<double>> _f; //!< Right hand side vector on each level.
|
||||||
|
std::vector<std::vector<double>> _d; //!< Defect vector on each level.
|
||||||
|
std::vector<std::vector<double>> _w; //!< Correction vector on each level.
|
||||||
|
std::vector<BisectIntDirichlet> _Pc2f; //!< Interpolation to level from next coarser level.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
8
sheet7/jacobi.template/laplacian.m
Normal file
8
sheet7/jacobi.template/laplacian.m
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
%% calculate -Laplacian of a function
|
||||||
|
syms x y c ;
|
||||||
|
u = x*x*sin(2.5*pi*y)
|
||||||
|
|
||||||
|
f = simplify(-laplacian(u,[x,y]))
|
||||||
|
|
||||||
|
fsurf(u,[0,1,0,1])
|
||||||
|
xlabel("x");ylabel("y");
|
||||||
94
sheet7/jacobi.template/main.cpp
Normal file
94
sheet7/jacobi.template/main.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
// MPI code in C++.
|
||||||
|
// See [Gropp/Lusk/Skjellum, "Using MPI", p.33/41 etc.]
|
||||||
|
// and /opt/mpich/include/mpi2c++/comm.h for details
|
||||||
|
|
||||||
|
#include "geom.h"
|
||||||
|
#include "getmatrix.h"
|
||||||
|
#include "jacsolve.h"
|
||||||
|
#include "par_geom.h"
|
||||||
|
#include "userset.h"
|
||||||
|
#include "vdop.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mpi.h> // MPI
|
||||||
|
#include <omp.h> // OpenMP
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc , char **argv )
|
||||||
|
{
|
||||||
|
MPI_Init(&argc, &argv);
|
||||||
|
MPI_Comm const icomm(MPI_COMM_WORLD);
|
||||||
|
omp_set_num_threads(1); // don't use OMP parallelization for a start
|
||||||
|
//
|
||||||
|
{
|
||||||
|
int np;
|
||||||
|
MPI_Comm_size(icomm, &np);
|
||||||
|
|
||||||
|
//assert(4 == np); // example is only provided for 4 MPI processes
|
||||||
|
}
|
||||||
|
// #####################################################################
|
||||||
|
// ---- Read the f.e. mesh and the mapping of elements to MPI processes
|
||||||
|
//Mesh const mesh_c("square_4.txt"); // Files square_4.m and square_4_sd.txt are needed
|
||||||
|
//ParMesh const mesh("square_bb");
|
||||||
|
ParMesh const mesh("../generate_mesh/rec");
|
||||||
|
//ParMesh const mesh("../generate_mesh/rec_a");
|
||||||
|
|
||||||
|
int const numprocs = mesh.NumProcs();
|
||||||
|
int const myrank = mesh.MyRank();
|
||||||
|
if ( 0 == myrank )
|
||||||
|
{
|
||||||
|
cout << "\n There are " << numprocs << " processes running.\n \n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int const check_rank = 0; // choose the MPI process you would like to check the mesh
|
||||||
|
//if ( check_rank == myrank ) mesh.Debug();
|
||||||
|
//if ( check_rank == myrank ) mesh.DebugEdgeBased();
|
||||||
|
|
||||||
|
|
||||||
|
FEM_Matrix SK(mesh); // CRS matrix
|
||||||
|
//SK.Debug();
|
||||||
|
|
||||||
|
vector<double> uv(SK.Nrows(), 0.0); // temperature
|
||||||
|
vector<double> fv(SK.Nrows(), 0.0); // r.h.s.
|
||||||
|
|
||||||
|
mesh.VecAccu(uv); // Check MPI comm.
|
||||||
|
|
||||||
|
SK.CalculateLaplace(fv);
|
||||||
|
//SK.Debug();
|
||||||
|
//
|
||||||
|
mesh.SetValues(uv, [](double x, double y) -> double
|
||||||
|
{
|
||||||
|
return x *x * std::sin(2.5 * M_PI * y);
|
||||||
|
} );
|
||||||
|
|
||||||
|
////mesh.SetU(uv); // deprecated
|
||||||
|
//// Two ways to initialize the vector
|
||||||
|
////mesh.SetValues(uv,f_zero); // user function
|
||||||
|
////mesh.SetValues(uv, [](double x, double y) -> double {return 0.0*x*y;} ); // lambda function
|
||||||
|
////mesh.SetValues(uv, [](double x, double y) -> double {return 5e-3*(x+1)*(y+1);} ); // lambda function
|
||||||
|
////
|
||||||
|
//mesh.SetValues(uv, [](double x, double y) -> double {
|
||||||
|
//return x * x * std::sin(2.5 * M_PI * y);
|
||||||
|
//} );
|
||||||
|
|
||||||
|
SK.ApplyDirichletBC(uv, fv);
|
||||||
|
//SK.Debug();
|
||||||
|
|
||||||
|
double tstart = MPI_Wtime(); // Wall clock
|
||||||
|
|
||||||
|
JacobiSolve(SK, fv, uv ); // solve the system of equations
|
||||||
|
//JacobiSolve(mesh, SK, fv, uv ); // MPI: solve the system of equations
|
||||||
|
|
||||||
|
double t1 = MPI_Wtime() - tstart; // Wall clock
|
||||||
|
cout << "JacobiSolve: timing in sec. : " << t1 << endl;
|
||||||
|
|
||||||
|
//if (2==myrank || (1==numprocs && 0==myrank) ) mesh.Mesh::Visualize(uv); // Visualize only one subdomain
|
||||||
|
mesh.Visualize(uv); // Visualize all subdomains
|
||||||
|
|
||||||
|
MPI_Finalize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
75
sheet7/jacobi.template/mgrid.cbp
Normal file
75
sheet7/jacobi.template/mgrid.cbp
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<CodeBlocks_project_file>
|
||||||
|
<FileVersion major="1" minor="6" />
|
||||||
|
<Project>
|
||||||
|
<Option title="mgrid" />
|
||||||
|
<Option pch_mode="2" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<Build>
|
||||||
|
<Target title="Debug">
|
||||||
|
<Option output="bin/Debug/mgrid" prefix_auto="1" extension_auto="1" />
|
||||||
|
<Option object_output="obj/Debug/" />
|
||||||
|
<Option type="1" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-Wshadow" />
|
||||||
|
<Add option="-Winit-self" />
|
||||||
|
<Add option="-Wredundant-decls" />
|
||||||
|
<Add option="-Wcast-align" />
|
||||||
|
<Add option="-Wundef" />
|
||||||
|
<Add option="-Wunreachable-code" />
|
||||||
|
<Add option="-Wmissing-declarations" />
|
||||||
|
<Add option="-Wswitch-enum" />
|
||||||
|
<Add option="-Wswitch-default" />
|
||||||
|
<Add option="-Weffc++" />
|
||||||
|
<Add option="-pedantic" />
|
||||||
|
<Add option="-Wextra" />
|
||||||
|
<Add option="-Wall" />
|
||||||
|
<Add option="-g" />
|
||||||
|
</Compiler>
|
||||||
|
</Target>
|
||||||
|
<Target title="Release">
|
||||||
|
<Option output="bin/Release/mgrid" prefix_auto="1" extension_auto="1" />
|
||||||
|
<Option object_output="obj/Release/" />
|
||||||
|
<Option type="1" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-O2" />
|
||||||
|
</Compiler>
|
||||||
|
<Linker>
|
||||||
|
<Add option="-s" />
|
||||||
|
</Linker>
|
||||||
|
</Target>
|
||||||
|
</Build>
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-std=c++11" />
|
||||||
|
<Add option="-fexceptions" />
|
||||||
|
</Compiler>
|
||||||
|
<Unit filename="geom.cpp" />
|
||||||
|
<Unit filename="geom.h" />
|
||||||
|
<Unit filename="getmatrix.cpp" />
|
||||||
|
<Unit filename="getmatrix.h" />
|
||||||
|
<Unit filename="jacsolve.cpp" />
|
||||||
|
<Unit filename="jacsolve.h" />
|
||||||
|
<Unit filename="main.cpp" />
|
||||||
|
<Unit filename="userset.cpp" />
|
||||||
|
<Unit filename="userset.h" />
|
||||||
|
<Unit filename="vdop.cpp" />
|
||||||
|
<Unit filename="vdop.h" />
|
||||||
|
<Extensions>
|
||||||
|
<envvars />
|
||||||
|
<code_completion />
|
||||||
|
<lib_finder disable_auto="1" />
|
||||||
|
<debugger />
|
||||||
|
<DoxyBlocks>
|
||||||
|
<comment_style block="1" line="1" />
|
||||||
|
<doxyfile_project />
|
||||||
|
<doxyfile_build extract_all="1" />
|
||||||
|
<doxyfile_warnings />
|
||||||
|
<doxyfile_output />
|
||||||
|
<doxyfile_dot class_diagrams="1" have_dot="1" />
|
||||||
|
<general />
|
||||||
|
</DoxyBlocks>
|
||||||
|
</Extensions>
|
||||||
|
</Project>
|
||||||
|
</CodeBlocks_project_file>
|
||||||
625
sheet7/jacobi.template/par_geom.cpp
Normal file
625
sheet7/jacobi.template/par_geom.cpp
Normal file
|
|
@ -0,0 +1,625 @@
|
||||||
|
// see: http://llvm.org/docs/CodingStandards.html#include-style
|
||||||
|
#include "vdop.h"
|
||||||
|
//#include "geom.h"
|
||||||
|
#include "par_geom.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <ctime> // contains clock()
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <numeric> // accumulate()
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
ParMesh::ParMesh(int ndim, int nvert_e, int ndof_e, int nedge_e, MPI_Comm const &icomm)
|
||||||
|
: Mesh(ndim, nvert_e, ndof_e, nedge_e),
|
||||||
|
_icomm(icomm), _numprocs(-1), _myrank(-1),
|
||||||
|
_v_l2g(0), _t_l2g(0), _v_g2l{{}}, _t_g2l{{}}, _valence(0),
|
||||||
|
_sendbuf(0), _sendcounts(0), _sdispls(0),
|
||||||
|
_loc_itf(0), _gloc_itf(0), _buf2loc(0)
|
||||||
|
{
|
||||||
|
MPI_Comm_size(icomm, &_numprocs);
|
||||||
|
MPI_Comm_rank(icomm, &_myrank);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParMesh::~ParMesh()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ParMesh::ParMesh(std::string const &sname, MPI_Comm const &icomm)
|
||||||
|
: ParMesh(2, 3, 3, 3, icomm) // two dimensions, 3 vertices, 3 dofs, 3 edges per element
|
||||||
|
{
|
||||||
|
//const int numprocs = _icomm.Get_size();
|
||||||
|
const string NS = "_" + to_string(_numprocs);
|
||||||
|
const string fname = sname + NS + ".txt";
|
||||||
|
//cout << "############ " << fname << endl;
|
||||||
|
ReadVertexBasedMesh(fname);
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Until this point a l l processes possess a l l mesh info in g l o b a l numbering
|
||||||
|
//
|
||||||
|
// Now, we have to select the data belonging to my_rank
|
||||||
|
// and we have to create the mapping local to global (l2g) and vice versa (g2l)
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// save the global node mesh (maybe we need it later)
|
||||||
|
DeriveEdgeFromVertexBased(); // and even more
|
||||||
|
Mesh global_mesh(*this); // requires a l o t of memory
|
||||||
|
Del_EdgeConnectivity();
|
||||||
|
|
||||||
|
// read the subdomain info
|
||||||
|
const string dname = sname + NS + "_sd" + ".txt";
|
||||||
|
vector<int> t2d = ReadElementSubdomains(dname); // global mapping triangle to subdomain for all elements
|
||||||
|
|
||||||
|
//const int myrank = _icomm.Get_rank();
|
||||||
|
Transform_Local2Global_Vertex(_myrank, t2d); // Vertex based mesh: now in l o c a l indexing
|
||||||
|
|
||||||
|
DeriveEdgeFromVertexBased(); // Generate also the l o c a l edge based information
|
||||||
|
|
||||||
|
Generate_VectorAdd();
|
||||||
|
|
||||||
|
|
||||||
|
// Now we have to organize the MPI communication of vertices on the subdomain interfaces
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<int> ParMesh::ReadElementSubdomains(string const &dname)
|
||||||
|
{
|
||||||
|
ifstream ifs(dname);
|
||||||
|
if (!(ifs.is_open() && ifs.good())) {
|
||||||
|
cerr << "ParMesh::ReadElementSubdomain: Error cannot open file " << dname << endl;
|
||||||
|
assert(ifs.is_open());
|
||||||
|
}
|
||||||
|
|
||||||
|
int const OFFSET{1}; // Matlab to C indexing
|
||||||
|
cout << "ASCI file " << dname << " opened" << endl;
|
||||||
|
|
||||||
|
// Read some mesh constants
|
||||||
|
int nelem;
|
||||||
|
ifs >> nelem;
|
||||||
|
cout << nelem << " " << Nelems() << endl;
|
||||||
|
assert( Nelems() == nelem);
|
||||||
|
|
||||||
|
// Allocate memory
|
||||||
|
vector<int> t2d(nelem, -1);
|
||||||
|
// Read element mapping
|
||||||
|
for (int k = 0; k < nelem; ++k) {
|
||||||
|
int tmp;
|
||||||
|
ifs >> tmp;
|
||||||
|
//t2d[k] = tmp - OFFSET;
|
||||||
|
// 2020-01-08
|
||||||
|
t2d[k] = min(tmp, NumProcs()) - OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParMesh::Transform_Local2Global_Vertex(int const myrank, vector<int> const &t2d)
|
||||||
|
{
|
||||||
|
// number of local elements
|
||||||
|
const int l_ne = count(t2d.cbegin(), t2d.cend(), myrank);
|
||||||
|
//cout << myrank << ":: " << lne << endl;
|
||||||
|
vector<int> l_ia(l_ne * NverticesElements(), -1); // local elements still with global vertex numbers
|
||||||
|
_t_l2g.resize(l_ne, -1);
|
||||||
|
|
||||||
|
int lk = 0;
|
||||||
|
for (size_t k = 0; k < t2d.size(); ++k) {
|
||||||
|
if (myrank == t2d[k]) {
|
||||||
|
//if (0==myrank)
|
||||||
|
//{
|
||||||
|
//cout << lk << " k " << t2d[k] << endl;
|
||||||
|
//}
|
||||||
|
l_ia[3 * lk ] = _ia[3 * k ];
|
||||||
|
l_ia[3 * lk + 1] = _ia[3 * k + 1];
|
||||||
|
l_ia[3 * lk + 2] = _ia[3 * k + 2]; // local elements still with global vertex numbers
|
||||||
|
_t_l2g[lk] = k; // elements: local to global mapping
|
||||||
|
_t_g2l[k] = lk; // global to local
|
||||||
|
++lk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Checks:
|
||||||
|
assert( count(l_ia.cbegin(), l_ia.cend(), -1) == 0 );
|
||||||
|
assert( count(_t_l2g.cbegin(), _t_l2g.cend(), -1) == 0 );
|
||||||
|
|
||||||
|
// Vertices: local to global mapping
|
||||||
|
auto tmp = l_ia;
|
||||||
|
sort(tmp.begin(), tmp.end());
|
||||||
|
auto ip = unique(tmp.begin(), tmp.end());
|
||||||
|
tmp.erase(ip, tmp.end());
|
||||||
|
_v_l2g = tmp; // Vertices: local to global mapping
|
||||||
|
for (size_t lkv = 0; lkv < _v_l2g.size(); ++lkv) {
|
||||||
|
_v_g2l[_v_l2g[lkv]] = lkv; // global to local
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boundary edges
|
||||||
|
vector<int> l_bedges;
|
||||||
|
vector<int> l_sdedges;
|
||||||
|
for (size_t b = 0; b < _bedges.size(); b += 2) {
|
||||||
|
int const v1 = _bedges[b ]; // global vertex numbers
|
||||||
|
int const v2 = _bedges[b + 1];
|
||||||
|
try {
|
||||||
|
int const lv1 = _v_g2l.at(v1); // map[] would add that element
|
||||||
|
int const lv2 = _v_g2l.at(v2); // but at() throws an exeption
|
||||||
|
l_bedges.push_back(lv1);
|
||||||
|
l_bedges.push_back(lv2); // Boundaries: already in local indexing
|
||||||
|
// 2020-01-08
|
||||||
|
l_sdedges.push_back(_sdedges[b ]);
|
||||||
|
l_sdedges.push_back(_sdedges[b+1]);
|
||||||
|
}
|
||||||
|
catch (std::out_of_range &err) {
|
||||||
|
//cerr << ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// number of local vertices
|
||||||
|
const int l_nn = _v_l2g.size();
|
||||||
|
vector<double> l_xc(Ndims()*l_nn);
|
||||||
|
for (int lkk = 0; lkk < l_nn; ++lkk) {
|
||||||
|
int k = _v_l2g.at(lkk);
|
||||||
|
l_xc[2 * lkk ] = _xc[2 * k ];
|
||||||
|
l_xc[2 * lkk + 1] = _xc[2 * k + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now, we represent the vertex mesh in l o c a l numbering
|
||||||
|
// elements
|
||||||
|
|
||||||
|
for (size_t i = 0; i < l_ia.size(); ++i) {
|
||||||
|
l_ia[i] = _v_g2l.at(l_ia[i]); // element vertices: global to local
|
||||||
|
}
|
||||||
|
SetNelem(l_ne);
|
||||||
|
_ia = l_ia;
|
||||||
|
// boundary
|
||||||
|
_bedges = l_bedges;
|
||||||
|
_sdedges = l_sdedges;
|
||||||
|
// coordinates
|
||||||
|
SetNnode(l_nn);
|
||||||
|
_xc = l_xc;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParMesh::Generate_VectorAdd()
|
||||||
|
{
|
||||||
|
// Some checks
|
||||||
|
int lnn = Nnodes(); // local number of vertices
|
||||||
|
assert(static_cast<int>(_v_l2g.size()) == lnn);
|
||||||
|
int ierr{-12345};
|
||||||
|
|
||||||
|
// ---- Determine global largest vertex index
|
||||||
|
int gidx_max{-1}; // global largest vertex index
|
||||||
|
int lmax = *max_element(_v_l2g.cbegin(), _v_l2g.cend());
|
||||||
|
MPI_Allreduce(&lmax, &gidx_max, 1, MPI_INT, MPI_MAX, _icomm);
|
||||||
|
int gidx_min{-1}; // global smallest vertex index
|
||||||
|
int lmin = *min_element(_v_l2g.cbegin(), _v_l2g.cend());
|
||||||
|
MPI_Allreduce(&lmin, &gidx_min, 1, MPI_INT, MPI_MIN, _icomm);
|
||||||
|
//cout << gidx_min << " " << gidx_max << endl;
|
||||||
|
assert(0 == gidx_min); // global indices have to start with 0
|
||||||
|
|
||||||
|
|
||||||
|
// ---- Determine for all global vertices the number of subdomains it belongs to
|
||||||
|
vector<int> global(gidx_max+1, 0); // global scalar array for vertices
|
||||||
|
for (auto const gidx : _v_l2g) global[gidx] = 1;
|
||||||
|
// https://www.mpi-forum.org/docs/mpi-2.2/mpi22-report/node109.htm
|
||||||
|
ierr = MPI_Allreduce(MPI_IN_PLACE, global.data(), global.size(), MPI_INT, MPI_SUM, _icomm);
|
||||||
|
//if (0 == MyRank()) cout << global << endl;
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//cout << _xc[2*_v_g2l.at(2)] << " , " << _xc[2*_v_g2l.at(2)+1] << endl;
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
|
||||||
|
// now, global[] contains the number of subdomains a global vertex belongs to
|
||||||
|
if ( count(global.cbegin(), global.cend(), 0) > 0 )
|
||||||
|
cerr << "\n !!! Non-continuous global vertex indexing !!!\n";
|
||||||
|
|
||||||
|
// ---- Determine local interface vertices ( <==> global[] > 1 )
|
||||||
|
// _loc_itf, neigh_itf
|
||||||
|
//vector<int> loc_itf; // local indices of interface vertices on this MPI process
|
||||||
|
for (size_t lk = 0; lk < _v_l2g.size(); ++lk) {
|
||||||
|
int const gk = _v_l2g[lk]; // global index of local vertex lk
|
||||||
|
if ( global[gk] > 1 ) {
|
||||||
|
_loc_itf.push_back(lk); // local indices of interface vertices on this MPI process
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//if (0 == MyRank()) cout << "\n..._loc_itf...\n" << _loc_itf << "\n......\n";
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
// ---- global indices of local interface vertices
|
||||||
|
//auto gloc_itf(_loc_itf);
|
||||||
|
_gloc_itf=_loc_itf;
|
||||||
|
for_each(_gloc_itf.begin(), _gloc_itf.end(), [this] (auto & v) -> void { v = _v_l2g[v];} );
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//if (0 == MyRank()) cout << "\n..._gloc_itf...\n" << _gloc_itf << "\n......\n";
|
||||||
|
//DebugVector(_gloc_itf,"_gloc_itf");
|
||||||
|
|
||||||
|
// ---- Determine the global length of interfaces
|
||||||
|
vector<int> vnn(NumProcs(), -1); // number of interface vertices per MPI rank
|
||||||
|
int l_itf(_loc_itf.size()); // # local interface vertices
|
||||||
|
ierr = MPI_Allgather(&l_itf, 1, MPI_INT, vnn.data(), 1, MPI_INT, _icomm);
|
||||||
|
assert(0 == ierr);
|
||||||
|
//cout << vnn << endl;
|
||||||
|
|
||||||
|
// ---- Now we consider only the inferface vertices
|
||||||
|
int snn = accumulate(vnn.cbegin(), vnn.cend(), 0); // required length of array for global interface indices
|
||||||
|
//cout << snn << " " << gnn << endl;
|
||||||
|
vector<int> dispnn(NumProcs(), 0) ; // displacement of interface vertices per MPI rank
|
||||||
|
partial_sum(vnn.cbegin(), vnn.cend() - 1, dispnn.begin() + 1);
|
||||||
|
//cout << dispnn << endl;
|
||||||
|
|
||||||
|
// ---- Get the global indices for all global interfaces
|
||||||
|
vector<int> g_itf(snn, -1); // collects all global indices of the global interfaces
|
||||||
|
// https://www.mpich.org/static//docs/v3.0.x/www3/MPI_Gatherv.html
|
||||||
|
ierr = MPI_Gatherv( _gloc_itf.data(), _gloc_itf.size(), MPI_INT,
|
||||||
|
g_itf.data(), vnn.data(), dispnn.data(), MPI_INT, 0, _icomm);
|
||||||
|
assert(0 == ierr);
|
||||||
|
// https://www.mpich.org/static/docs/v3.1/www3/MPI_Bcast.html
|
||||||
|
ierr = MPI_Bcast(g_itf.data(), g_itf.size(), MPI_INT, 0, _icomm);
|
||||||
|
assert(0 == ierr); // Now, each MPI rank has the all global indices of the global interfaces
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
//if (MyRank() == 0) cout << "\n...g_itf...\n" << g_itf << "\n......\n";
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
|
||||||
|
// ----- Determine all MPI ranks a local interface vertex belongs to
|
||||||
|
vector<vector<int>> neigh_itf(_loc_itf.size());// subdomains a local interface vertex belongs to
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk) {
|
||||||
|
const int gvert = _gloc_itf[lk]; // global index of local interface node lk
|
||||||
|
for (int rank = 0; rank < NumProcs(); ++rank) {
|
||||||
|
auto const startl = g_itf.cbegin() + dispnn[rank];
|
||||||
|
auto const endl = startl + vnn[rank];
|
||||||
|
if ( find( startl, endl, gvert) != endl) {
|
||||||
|
neigh_itf[lk].push_back(rank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- check the available info in _loc_itf[lk], _gloc_itf[lk], neigh_itf[lk]
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
////if (MyRank()==0) cout << "\n...neigh_itf ...\n" << neigh_itf << endl;
|
||||||
|
//if (MyRank() == 0) {
|
||||||
|
//for (size_t lk = 0; lk < _loc_itf.size(); ++lk ) {
|
||||||
|
//cout << lk << " : local idx " << _loc_itf[lk] << " , global idx " << _gloc_itf[lk];
|
||||||
|
//cout << " with MPI ranks " << neigh_itf[lk] << endl;
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//MPI_Barrier(_icomm);
|
||||||
|
|
||||||
|
// ---- store the valence (e.g., the number of subdomains it belongs to) of all local vertices
|
||||||
|
_valence.resize(Nnodes(),1);
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk)
|
||||||
|
{
|
||||||
|
_valence[_loc_itf[lk]] = neigh_itf[lk].size();
|
||||||
|
}
|
||||||
|
//DebugVector(_valence,"_valence",_icomm);
|
||||||
|
|
||||||
|
// ---- We ware going to use MPI_Alltoallv for data exchange on interfaces
|
||||||
|
// https://www.mpi-forum.org/docs/mpi-3.1/mpi31-report/node109.htm#Node109
|
||||||
|
// https://www.open-mpi.org/doc/v4.0/man3/MPI_Alltoallv.3.php
|
||||||
|
//int MPI_Alltoallv(const void* sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype, void* recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype, MPI_Comm comm)
|
||||||
|
//
|
||||||
|
// MPI_Alltoallv needs:
|
||||||
|
// vector<double> sendbuf (MPI_IN_PLACE: used also as recvbuf)
|
||||||
|
// vector<int> sendcounts (the same as for recv)
|
||||||
|
// vector<int> sdispls (the same as for recv)
|
||||||
|
//
|
||||||
|
// We need to map the interface vertices onto the sendbuffer:
|
||||||
|
// vector<int> loc_itf local index of interface vertex lk
|
||||||
|
// vector<int> gloc_itf global index of interface vertex lk
|
||||||
|
// vector<int> buf2loc local indices of sendbuffer positions (the same as for recv)
|
||||||
|
|
||||||
|
// ---- Determine sendcounts[] and sdipls[] from neigh_itf[]
|
||||||
|
//vector<int> _sendcounts(NumProcs(), 0);
|
||||||
|
_sendcounts.resize(NumProcs(), 0);
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk ) {
|
||||||
|
auto const &kneigh = neigh_itf[lk];
|
||||||
|
for (size_t ns = 0; ns < kneigh.size(); ++ns) {
|
||||||
|
++_sendcounts[kneigh[ns]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (MyRank() == 0) cout << "\n..._sendcounts ...\n" << _sendcounts << endl;
|
||||||
|
|
||||||
|
//vector<int> _sdispls(NumProcs(), 0);
|
||||||
|
_sdispls.resize(NumProcs(), 0);
|
||||||
|
partial_sum(_sendcounts.cbegin(), _sendcounts.cend() - 1, _sdispls.begin() + 1);
|
||||||
|
//vector<int> _sdispls(NumProcs()+1, 0);
|
||||||
|
//partial_sum(_sendcounts.cbegin(), _sendcounts.cend(), _sdispls.begin() + 1);
|
||||||
|
//if (MyRank() == 0) cout << "\n..._sdispls ...\n" << _sdispls << endl;
|
||||||
|
|
||||||
|
// ---- Determine size of buffer 'nbuffer' and mapping 'buf2loc'
|
||||||
|
int const nbuffer = accumulate(_sendcounts.cbegin(), _sendcounts.cend(), 0);
|
||||||
|
//vector<int> _buf2loc(nbuffer, -1);
|
||||||
|
_buf2loc.resize(nbuffer, -1);
|
||||||
|
int buf_idx = 0; // position in buffer
|
||||||
|
for (int rank = 0; rank < NumProcs(); ++rank) {
|
||||||
|
assert( buf_idx == _sdispls[rank]);
|
||||||
|
for (size_t lk = 0; lk < _loc_itf.size(); ++lk ) {
|
||||||
|
auto const &kneigh = neigh_itf[lk];
|
||||||
|
if (find(kneigh.cbegin(),kneigh.cend(),rank)!=kneigh.cend())
|
||||||
|
{
|
||||||
|
_buf2loc[buf_idx] = _loc_itf[lk];
|
||||||
|
++buf_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (MyRank() == 0) cout << "\n...buf2loc ...\n" << buf2loc << endl;
|
||||||
|
//DebugVector(buf2loc,"buf2loc",_icomm);
|
||||||
|
|
||||||
|
// ---- Allocate send/recv buffer
|
||||||
|
//vector<double> _sendbuf(nbuffer,-1.0);
|
||||||
|
_sendbuf.resize(nbuffer,-1.0);
|
||||||
|
|
||||||
|
assert(CheckInterfaceExchange_InPlace());
|
||||||
|
cout << " Check of data exchange (InPlace) successful!\n";
|
||||||
|
assert(CheckInterfaceExchange());
|
||||||
|
cout << " Check of data exchange successful!\n";
|
||||||
|
assert(CheckInterfaceAdd_InPlace());
|
||||||
|
cout << " Check of data add successful!\n";
|
||||||
|
assert(CheckInterfaceAdd());
|
||||||
|
cout << " Check of data add (InPlace) successful!\n";
|
||||||
|
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
VecAccu(x);
|
||||||
|
cout << " VecAccu (InPlace) successful!\n";
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceExchange_InPlace() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
copy(_v_l2g.cbegin(),_v_l2g.cend(),x.begin()); // init x with global vertex indices
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
int ierr = MPI_Alltoallv(MPI_IN_PLACE, _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = -1.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
y[_buf2loc.at(ls)] = _sendbuf[ls];
|
||||||
|
}
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceExchange() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
copy(_v_l2g.cbegin(),_v_l2g.cend(),x.begin()); // init x with global vertex indices
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
vector<double> recvbuf(_sendbuf.size());
|
||||||
|
int ierr = MPI_Alltoallv(_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
recvbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
//DebugVector(recvbuf,"recvbuf",_icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = -1.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<recvbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
y[_buf2loc.at(ls)] = recvbuf[ls];
|
||||||
|
}
|
||||||
|
//cout << "WRONG : " << count(y.cbegin(),y.cend(), -1.0) << endl;
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceAdd_InPlace() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
for (size_t i=0; i<x.size(); ++i)
|
||||||
|
{
|
||||||
|
x[i] = _xc[2*i]+_xc[2*i+1]; // init x with coordinate values
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
int ierr = MPI_Alltoallv(MPI_IN_PLACE, _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = 0.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
y[_buf2loc.at(ls)] += _sendbuf[ls];
|
||||||
|
}
|
||||||
|
MPI_Barrier(_icomm);
|
||||||
|
//DebugVector(x,"x",_icomm);
|
||||||
|
//DebugVector(y,"y",_icomm);
|
||||||
|
for (size_t i= 0; i<y.size(); ++i) y[i]/=_valence[i]; // divide by valence
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParMesh::CheckInterfaceAdd() const
|
||||||
|
{
|
||||||
|
vector<double> x(Nnodes(),-1.0);
|
||||||
|
for (size_t i=0; i<x.size(); ++i)
|
||||||
|
{
|
||||||
|
//x[i] = _xc[2*i]+_xc[2*i+1]; // init x with coordinate values
|
||||||
|
x[i] = _v_l2g[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = x[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
vector<double> recvbuf(_sendbuf.size());
|
||||||
|
int ierr = MPI_Alltoallv(_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
recvbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
//DebugVector(recvbuf,"recvbuf",_icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
|
||||||
|
vector<double> y(x);
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) y[_loc_itf.at(lk)] = 0.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<recvbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
//if (0==MyRank()) cout << ls << ": " << _buf2loc.at(ls) << " " << y[_buf2loc.at(ls)] << "("<< x[_buf2loc.at(ls)] << ")" << " " << recvbuf[ls] << " (" << _sendbuf[ls] << ")" << endl;
|
||||||
|
y[_buf2loc.at(ls)] += recvbuf[ls];
|
||||||
|
}
|
||||||
|
MPI_Barrier(_icomm);
|
||||||
|
//DebugVector(x,"x",_icomm);
|
||||||
|
//DebugVector(y,"y",_icomm);
|
||||||
|
for (size_t i= 0; i<y.size(); ++i) y[i]/=_valence[i]; // divide by valence
|
||||||
|
|
||||||
|
double const eps=1e-10;
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y.cbegin(),
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
return bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
void ParMesh::VecAccu(std::vector<double> &w) const
|
||||||
|
{
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
_sendbuf[ls] = w[_buf2loc.at(ls)];
|
||||||
|
}
|
||||||
|
int ierr = MPI_Alltoallv(MPI_IN_PLACE, _sendcounts.data(), _sdispls.data(), MPI_DOUBLE,
|
||||||
|
_sendbuf.data(), _sendcounts.data(), _sdispls.data(), MPI_DOUBLE, _icomm);
|
||||||
|
assert(ierr==0);
|
||||||
|
//DebugVector(_sendbuf,"_sendbuf",_icomm);
|
||||||
|
|
||||||
|
for(size_t lk = 0; lk<_loc_itf.size(); ++lk) w[_loc_itf.at(lk)] = 0.0; // only for interface nodes
|
||||||
|
for(size_t ls = 0; ls<_sendbuf.size(); ++ls)
|
||||||
|
{
|
||||||
|
w[_buf2loc.at(ls)] += _sendbuf[ls];
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
/*
|
||||||
|
manjaro> matlab
|
||||||
|
MATLAB is selecting SOFTWARE OPENGL rendering.
|
||||||
|
/usr/local/MATLAB/R2019a/bin/glnxa64/MATLAB: error while loading shared libraries: libcrypt.so.1: cannot open shared object file: No such file or directory
|
||||||
|
|
||||||
|
SOLUTION: sudo pacman -S libxcrypt-compat + reboot
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ParMesh::Visualize(vector<double> const &v) const
|
||||||
|
{
|
||||||
|
// define external command, but we have to pass the number of subdomains
|
||||||
|
string const MatlabScript{"visualize_par_results("+ to_string(_numprocs) + ")"};
|
||||||
|
|
||||||
|
// define the command to be executed
|
||||||
|
string const exec_m("matlab -nosplash -nodesktop -r '" + MatlabScript + "; quit'"); // Matlab
|
||||||
|
//string const exec_m("octave --no-window-system --no-gui '"+MatlabScript+"'"); // Octave, until version 6.3
|
||||||
|
//string const exec_m("octave --no-gui --eval '"+MatlabScript+"'"); // Octave since version 6.4
|
||||||
|
//string const exec_m("flatpak run org.octave.Octave --eval '"+MatlabScript+"'"); // Octave (flatpak): desktop GH
|
||||||
|
|
||||||
|
// old calls
|
||||||
|
//const string exec_m("matlab -nosplash -nodesktop -r 'try visualize_par_results("+ to_string(_numprocs) + "); catch; end; quit'"); // Matlab old
|
||||||
|
//const string exec_m("octave --no-window-system --no-gui visualize_par_results.m"); // Octave old
|
||||||
|
|
||||||
|
const string pre{"uv_"};
|
||||||
|
const string post{".txt"};
|
||||||
|
const string fname(pre + to_string(_myrank) + post);
|
||||||
|
|
||||||
|
if (0 == _myrank)
|
||||||
|
{
|
||||||
|
cout << exec_m << endl;
|
||||||
|
cout << fname << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int p = 0; p <= NumProcs(); ++p) {
|
||||||
|
if (MyRank() == p) Write_ascii_matlab(fname, v);
|
||||||
|
MPI_Barrier(_icomm);
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Barrier(_icomm);
|
||||||
|
if (0 == _myrank)
|
||||||
|
{
|
||||||
|
int ierror = system(exec_m.c_str()); // call external command
|
||||||
|
if (ierror != 0)
|
||||||
|
{
|
||||||
|
cout << endl << "Check path to Matlab/octave on your system" << endl;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
MPI_Barrier(_icomm);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
160
sheet7/jacobi.template/par_geom.h
Normal file
160
sheet7/jacobi.template/par_geom.h
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
#ifndef PAR_GEOM_FILE
|
||||||
|
#define PAR_GEOM_FILE
|
||||||
|
#include "geom.h"
|
||||||
|
#include "vdop.h"
|
||||||
|
#include <array>
|
||||||
|
#include <functional> // function; C++11
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <memory> // shared_ptr
|
||||||
|
#include <mpi.h> // MPI
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ParMesh: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor initializing the members with default values.
|
||||||
|
*
|
||||||
|
* @param[in] ndim space dimensions (dimension for coordinates)
|
||||||
|
* @param[in] nvert_e number of vertices per element (dimension for connectivity)
|
||||||
|
* @param[in] ndof_e degrees of freedom per element (= @p nvert_e for linear elements)
|
||||||
|
* @param[in] nedge_e number of edges per element (= @p nvert_e for linear elements in 2D)
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
*/
|
||||||
|
explicit ParMesh(int ndim, int nvert_e = 0, int ndof_e = 0, int nedge_e = 0, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
ParMesh(ParMesh const &) = default;
|
||||||
|
|
||||||
|
ParMesh &operator=(ParMesh const &) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*
|
||||||
|
* See clang warning on
|
||||||
|
* <a href="https://stackoverflow.com/questions/28786473/clang-no-out-of-line-virtual-method-definitions-pure-abstract-c-class/40550578">weak-vtables</a>.
|
||||||
|
*/
|
||||||
|
virtual ~ParMesh();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* @param[in] sname suffix of file name
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
* @see ascii_write_mesh.m for the file format.
|
||||||
|
*/
|
||||||
|
explicit ParMesh(std::string const &sname, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
void VecAccu(std::vector<double> &w) const;
|
||||||
|
|
||||||
|
/** Inner product
|
||||||
|
* @param[in] x vector
|
||||||
|
* @param[in] y vector
|
||||||
|
* @return resulting Euclidian inner product <x,y>
|
||||||
|
*/
|
||||||
|
double dscapr(std::vector<double> const &x, std::vector<double> const &y) const
|
||||||
|
{
|
||||||
|
return par_scalar(x, y, _icomm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualize @p v together with its mesh information via matlab or octave.
|
||||||
|
*
|
||||||
|
* Comment/uncomment those code lines in method Mesh:Visualize (geom.cpp)
|
||||||
|
* that are supported on your system.
|
||||||
|
*
|
||||||
|
* @param[in] v vector
|
||||||
|
*
|
||||||
|
* @warning matlab files ascii_read_meshvector.m visualize_results.m
|
||||||
|
* must be in the executing directory.
|
||||||
|
*/
|
||||||
|
void Visualize(std::vector<double> const &v) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Reads the global triangle to subdomain mapping.
|
||||||
|
*
|
||||||
|
* @param[in] dname file name
|
||||||
|
*
|
||||||
|
* @see ascii_write_subdomains.m for the file format
|
||||||
|
*/
|
||||||
|
std::vector<int> ReadElementSubdomains(std::string const &dname);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform
|
||||||
|
*
|
||||||
|
* @param[in] myrank MPI rank of this process
|
||||||
|
* @param[in] t2d global mapping triangle to subdomain for all elements (vertex based)
|
||||||
|
*/
|
||||||
|
void Transform_Local2Global_Vertex(int myrank, std::vector<int> const &t2d);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform
|
||||||
|
*/
|
||||||
|
void Generate_VectorAdd();
|
||||||
|
|
||||||
|
bool CheckInterfaceExchange_InPlace() const;
|
||||||
|
bool CheckInterfaceExchange() const;
|
||||||
|
bool CheckInterfaceAdd_InPlace() const;
|
||||||
|
bool CheckInterfaceAdd() const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** MPI rank of the calling process in communication group.
|
||||||
|
*
|
||||||
|
* @return MPI rank of the calling process
|
||||||
|
*/
|
||||||
|
int MyRank() const
|
||||||
|
{
|
||||||
|
return _myrank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Number of MPI processes in communication group.
|
||||||
|
*
|
||||||
|
* @return Number of MPI processes
|
||||||
|
*/
|
||||||
|
int NumProcs() const
|
||||||
|
{
|
||||||
|
return _numprocs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns recent
|
||||||
|
* @return MPI communicator
|
||||||
|
*/
|
||||||
|
MPI_Comm GetCommunicator() const
|
||||||
|
{
|
||||||
|
return _icomm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Don't use &_icomm ==> Error
|
||||||
|
MPI_Comm const _icomm; //!< MPI communicator for the group of processes
|
||||||
|
int _numprocs; //!< number of MPI processes
|
||||||
|
int _myrank; //!< my MPI rank
|
||||||
|
std::vector<int> _v_l2g; //!< vertices: local to global mapping
|
||||||
|
std::vector<int> _t_l2g; //!< triangles: local to global mapping
|
||||||
|
std::map<int, int> _v_g2l; //!< vertices: global to local mapping
|
||||||
|
std::map<int, int> _t_g2l; //!< triangles: global to local mapping
|
||||||
|
|
||||||
|
//std::vector<int> e_l2g; //!< edges: local to global mapping
|
||||||
|
|
||||||
|
std::vector<int> _valence; //!< valence of local vertices, i.e. number of subdomains they belong to
|
||||||
|
// MPI_Alltoallv needs:
|
||||||
|
mutable std::vector<double> _sendbuf; //!< send buffer a n d receiving buffer (MPI_IN_PLACE)
|
||||||
|
std::vector<int> _sendcounts; //!< number of data to send to each MPI rank (the same as for recv)
|
||||||
|
std::vector<int> _sdispls; //!< offset of data to send to each MPI rank wrt. _senbuffer (the same as for recv)
|
||||||
|
//
|
||||||
|
// We need to map the interface vertices onto the sendbuffer:
|
||||||
|
std::vector<int> _loc_itf; //!< local index of interface vertex lk
|
||||||
|
std::vector<int> _gloc_itf; //!< global index of interface vertex lk
|
||||||
|
std::vector<int> _buf2loc; //!< local indices of sendbuffer positions (the same as for recv)
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
42
sheet7/jacobi.template/square.m
Normal file
42
sheet7/jacobi.template/square.m
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
% Square:
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
% %% L-shape
|
||||||
|
% g=[2 0 2 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 1 0;
|
||||||
|
% 2 2 1 1 0.5 1 0;
|
||||||
|
% 2 1 1 0.5 2 1 0;
|
||||||
|
% 2 1 0 2 2 1 0;
|
||||||
|
% 2 0 0 2 0 1 0]';
|
||||||
|
|
||||||
|
%% square
|
||||||
|
g=[2 0 1 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 0 1 1 0;
|
||||||
|
2 1 0 1 1 1 0;
|
||||||
|
2 0 0 1 0 1 0]';
|
||||||
|
|
||||||
|
%[p,e,t] = initmesh(g,'hmax',0.01);
|
||||||
|
[p,e,t] = initmesh(g,'hmax',0.5);
|
||||||
|
pdemesh(p,e,t)
|
||||||
|
|
||||||
|
%% GH
|
||||||
|
% output from <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>
|
||||||
|
%
|
||||||
|
% coordinates p: [2][nnode]
|
||||||
|
% connectivity t: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
|
||||||
|
ascii_write_mesh( p, t, e, mfilename);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% tmp=t(1:3,:)
|
||||||
|
|
||||||
138487
sheet7/jacobi.template/square_100.txt
Normal file
138487
sheet7/jacobi.template/square_100.txt
Normal file
File diff suppressed because it is too large
Load diff
71
sheet7/jacobi.template/square_4.m
Normal file
71
sheet7/jacobi.template/square_4.m
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
% Square:
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
% %% L-shape
|
||||||
|
% g=[2 0 2 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 1 0;
|
||||||
|
% 2 2 1 1 0.5 1 0;
|
||||||
|
% 2 1 1 0.5 2 1 0;
|
||||||
|
% 2 1 0 2 2 1 0;
|
||||||
|
% 2 0 0 2 0 1 0]';
|
||||||
|
|
||||||
|
%% square
|
||||||
|
% g=[2 0 1 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 0;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0]';
|
||||||
|
|
||||||
|
% %% 2 squares
|
||||||
|
% g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 2;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0;
|
||||||
|
% 2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 2 0;
|
||||||
|
% 2 2 1 1 1 2 0
|
||||||
|
% ]';
|
||||||
|
|
||||||
|
%% 4 squares
|
||||||
|
g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 0 1 1 2;
|
||||||
|
2 1 0 1 1 1 3;
|
||||||
|
2 0 0 1 0 1 0;
|
||||||
|
2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 2 2 0 1 2 0;
|
||||||
|
2 2 1 1 1 2 4;
|
||||||
|
% 2 1 1 1 0 2 1;
|
||||||
|
% 2 0 1 1 1 3 1; % 3 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 1 2 3 4;
|
||||||
|
2 1 0 2 2 3 0;
|
||||||
|
2 0 0 2 1 3 0;
|
||||||
|
% 2 1 2 1 1 4 2; % 4 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 2 2 1 2 4 0;
|
||||||
|
2 2 1 2 2 4 0
|
||||||
|
% 2 1 1 2 1 4 3
|
||||||
|
]';
|
||||||
|
|
||||||
|
[p,e,t] = initmesh(g,'hmax',0.1);
|
||||||
|
pdemesh(p,e,t)
|
||||||
|
|
||||||
|
%% GH
|
||||||
|
% output from <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>
|
||||||
|
%
|
||||||
|
% coordinates p: [2][nnode]
|
||||||
|
% connectivity t: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
|
||||||
|
ascii_write_mesh( p, t, e, mfilename);
|
||||||
|
|
||||||
|
ascii_write_subdomains( p, t, e, mfilename);
|
||||||
|
|
||||||
|
|
||||||
|
% tmp=t(1:3,:)
|
||||||
|
|
||||||
BIN
sheet7/jacobi.template/square_4.pdf
Normal file
BIN
sheet7/jacobi.template/square_4.pdf
Normal file
Binary file not shown.
2176
sheet7/jacobi.template/square_4.txt
Normal file
2176
sheet7/jacobi.template/square_4.txt
Normal file
File diff suppressed because it is too large
Load diff
1335
sheet7/jacobi.template/square_4_sd.txt
Normal file
1335
sheet7/jacobi.template/square_4_sd.txt
Normal file
File diff suppressed because it is too large
Load diff
106
sheet7/jacobi.template/square_bb_4.m
Normal file
106
sheet7/jacobi.template/square_bb_4.m
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
% Square:
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
% %% L-shape
|
||||||
|
% g=[2 0 2 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 1 0;
|
||||||
|
% 2 2 1 1 0.5 1 0;
|
||||||
|
% 2 1 1 0.5 2 1 0;
|
||||||
|
% 2 1 0 2 2 1 0;
|
||||||
|
% 2 0 0 2 0 1 0]';
|
||||||
|
|
||||||
|
%% square
|
||||||
|
% g=[2 0 1 0 0 1 0; % #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 0;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0]';
|
||||||
|
|
||||||
|
% %% 2 squares
|
||||||
|
% g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 1 1 0 1 1 2;
|
||||||
|
% 2 1 0 1 1 1 0;
|
||||||
|
% 2 0 0 1 0 1 0;
|
||||||
|
% 2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
% 2 2 2 0 1 2 0;
|
||||||
|
% 2 2 1 1 1 2 0
|
||||||
|
% ]';
|
||||||
|
|
||||||
|
%% 4 squares
|
||||||
|
g=[2 0 1 0 0 1 0; % 1 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 0 1 1 2;
|
||||||
|
2 1 0 1 1 1 3;
|
||||||
|
2 0 0 1 0 1 0;
|
||||||
|
2 1 2 0 0 2 0; % 2 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 2 2 0 1 2 0;
|
||||||
|
2 2 1 1 1 2 4;
|
||||||
|
% 2 1 1 1 0 2 1;
|
||||||
|
% 2 0 1 1 1 3 1; % 3 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 1 1 1 2 3 4;
|
||||||
|
2 1 0 2 2 3 0;
|
||||||
|
2 0 0 2 1 3 0;
|
||||||
|
% 2 1 2 1 1 4 2; % 4 #vertices,v_1x, v_2x, v_1y, v_2y, subdomain_left, subdomain_right
|
||||||
|
2 2 2 1 2 4 0;
|
||||||
|
2 2 1 2 2 4 0
|
||||||
|
% 2 1 1 2 1 4 3
|
||||||
|
]';
|
||||||
|
|
||||||
|
%% Generate mesh from geometry
|
||||||
|
%
|
||||||
|
[p,e,t] = initmesh(g,'hmax',1); % works correctly
|
||||||
|
% p(1,15) = 1.51; %% angle in trangle > pi/2 ==> now the second refinement produces irregular meshes!
|
||||||
|
% p(1,15) = 1.7; %% angle in trangle > pi/2 ==> now the second refinement produces irregular meshes!
|
||||||
|
|
||||||
|
% ??
|
||||||
|
% https://de.mathworks.com/help/pde/ug/mesh-data-pet-triples.html
|
||||||
|
% generateMesh(...)
|
||||||
|
% mesh2Pet(...)
|
||||||
|
%
|
||||||
|
% [p,e,t] = initmesh(g); % problems in solution after 2 refinements
|
||||||
|
% [p,e,t] = initmesh(g,'hmax',0.5); % problems in solution after 2 refinements (peaks with h=0.5, oscillations in (1,1) for h=0.1
|
||||||
|
% [p,e,t] = initmesh(g,'hmax',0.1/4); % no problems in solution with 0 refinemnet steps
|
||||||
|
|
||||||
|
%% Show mesh
|
||||||
|
pdemesh(p,e,t)
|
||||||
|
% pdemesh(p,e,t,'NodeLabels','on')
|
||||||
|
|
||||||
|
%% Improve mesh
|
||||||
|
% min(pdetriq(p,t))
|
||||||
|
% p = jigglemesh(p,e,t,'opt','minimum','iter',inf);
|
||||||
|
% min(pdetriq(p,t))
|
||||||
|
% pdemesh(p,e,t)
|
||||||
|
|
||||||
|
%% Refine mesh, see comments in "Generate mesh from geometry"
|
||||||
|
%
|
||||||
|
% nrefine=8;
|
||||||
|
nrefine=2; %
|
||||||
|
for k=1:nrefine
|
||||||
|
[p,e,t] = refinemesh(g,p,e,t);
|
||||||
|
% p = jigglemesh(p,e,t,'opt','minimum','iter',inf); % improve mesh
|
||||||
|
min(pdetriq(p,t))
|
||||||
|
fprintf('refinement: %i nodes: %i triangles: %i \n', k, size(p,2), size(t,2))
|
||||||
|
end
|
||||||
|
% figure; pdemesh(p,e,t,'NodeLabels','on')
|
||||||
|
%
|
||||||
|
|
||||||
|
%% GH
|
||||||
|
% output from <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>
|
||||||
|
%
|
||||||
|
% coordinates p: [2][nnode]
|
||||||
|
% connectivity t: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
|
||||||
|
ascii_write_mesh( p, t, e, mfilename);
|
||||||
|
|
||||||
|
ascii_write_subdomains( p, t, e, mfilename);
|
||||||
|
|
||||||
|
|
||||||
|
% tmp=t(1:3,:)
|
||||||
|
|
||||||
726
sheet7/jacobi.template/square_bb_4.txt
Normal file
726
sheet7/jacobi.template/square_bb_4.txt
Normal file
|
|
@ -0,0 +1,726 @@
|
||||||
|
209
|
||||||
|
2
|
||||||
|
384
|
||||||
|
3
|
||||||
|
0 0
|
||||||
|
1 0
|
||||||
|
1 1
|
||||||
|
0 1
|
||||||
|
2 0
|
||||||
|
2 1
|
||||||
|
1 2
|
||||||
|
0 2
|
||||||
|
2 2
|
||||||
|
1.5 1.5
|
||||||
|
0.5 1.5
|
||||||
|
1.5 0.5
|
||||||
|
0.5 0.5
|
||||||
|
1 0.5
|
||||||
|
1.5 1
|
||||||
|
0.5 1
|
||||||
|
1 1.5
|
||||||
|
0.5 0
|
||||||
|
1 0.25
|
||||||
|
0.75 1
|
||||||
|
0 0.5
|
||||||
|
1.5 0
|
||||||
|
2 0.5
|
||||||
|
1.75 1
|
||||||
|
1 1.25
|
||||||
|
0.5 2
|
||||||
|
0 1.5
|
||||||
|
2 1.5
|
||||||
|
1.5 2
|
||||||
|
1 0.75
|
||||||
|
1.25 1
|
||||||
|
0.25 1
|
||||||
|
1 1.75
|
||||||
|
1.75 1.25
|
||||||
|
1.25 1.75
|
||||||
|
1.75 1.75
|
||||||
|
0.25 1.25
|
||||||
|
0.75 1.75
|
||||||
|
0.25 1.75
|
||||||
|
1.25 0.25
|
||||||
|
1.75 0.25
|
||||||
|
1.75 0.75
|
||||||
|
0.25 0.25
|
||||||
|
0.75 0.25
|
||||||
|
0.25 0.75
|
||||||
|
1.25 0.5
|
||||||
|
0.75 0.5
|
||||||
|
1.5 1.25
|
||||||
|
1.5 0.75
|
||||||
|
1.25 0.75
|
||||||
|
0.5 1.25
|
||||||
|
0.5 0.75
|
||||||
|
0.75 0.75
|
||||||
|
1.25 1.5
|
||||||
|
0.75 1.5
|
||||||
|
1.25 1.25
|
||||||
|
0.75 1.25
|
||||||
|
0.25 0
|
||||||
|
1 0.125
|
||||||
|
0.875 1
|
||||||
|
0 0.75
|
||||||
|
1.25 0
|
||||||
|
2 0.25
|
||||||
|
1.875 1
|
||||||
|
1 1.125
|
||||||
|
0.75 2
|
||||||
|
0 1.75
|
||||||
|
2 1.25
|
||||||
|
1.75 2
|
||||||
|
1 0.625
|
||||||
|
1.375 1
|
||||||
|
0.375 1
|
||||||
|
1 1.625
|
||||||
|
0.75 0
|
||||||
|
1 0.375
|
||||||
|
0.625 1
|
||||||
|
0 0.25
|
||||||
|
1.75 0
|
||||||
|
2 0.75
|
||||||
|
1.625 1
|
||||||
|
1 1.375
|
||||||
|
0.25 2
|
||||||
|
0 1.25
|
||||||
|
2 1.75
|
||||||
|
1.25 2
|
||||||
|
1 0.875
|
||||||
|
1.125 1
|
||||||
|
0.125 1
|
||||||
|
1 1.875
|
||||||
|
0.875 1.125
|
||||||
|
0.875 0.875
|
||||||
|
1.125 1.125
|
||||||
|
1.125 0.875
|
||||||
|
1.875 1.125
|
||||||
|
1.625 1.375
|
||||||
|
1.75 1.125
|
||||||
|
1.875 1.375
|
||||||
|
1.125 1.875
|
||||||
|
1.375 1.625
|
||||||
|
1.375 1.875
|
||||||
|
1.125 1.75
|
||||||
|
1.875 1.875
|
||||||
|
1.625 1.625
|
||||||
|
1.875 1.625
|
||||||
|
1.625 1.875
|
||||||
|
1.75 1.5
|
||||||
|
1.5 1.75
|
||||||
|
0.125 1.125
|
||||||
|
0.375 1.375
|
||||||
|
0.125 1.375
|
||||||
|
0.25 1.125
|
||||||
|
0.875 1.875
|
||||||
|
0.625 1.625
|
||||||
|
0.625 1.875
|
||||||
|
0.875 1.75
|
||||||
|
0.125 1.875
|
||||||
|
0.375 1.625
|
||||||
|
0.375 1.875
|
||||||
|
0.125 1.625
|
||||||
|
0.25 1.5
|
||||||
|
0.5 1.75
|
||||||
|
1.125 0.125
|
||||||
|
1.375 0.375
|
||||||
|
1.125 0.25
|
||||||
|
1.375 0.125
|
||||||
|
1.875 0.125
|
||||||
|
1.625 0.375
|
||||||
|
1.625 0.125
|
||||||
|
1.875 0.375
|
||||||
|
1.5 0.25
|
||||||
|
1.875 0.875
|
||||||
|
1.625 0.625
|
||||||
|
1.875 0.625
|
||||||
|
1.75 0.875
|
||||||
|
1.75 0.5
|
||||||
|
0.125 0.125
|
||||||
|
0.375 0.375
|
||||||
|
0.375 0.125
|
||||||
|
0.125 0.375
|
||||||
|
0.875 0.125
|
||||||
|
0.625 0.375
|
||||||
|
0.625 0.125
|
||||||
|
0.875 0.25
|
||||||
|
0.5 0.25
|
||||||
|
0.125 0.875
|
||||||
|
0.375 0.625
|
||||||
|
0.125 0.625
|
||||||
|
0.25 0.875
|
||||||
|
0.25 0.5
|
||||||
|
1.375 0.5
|
||||||
|
1.125 0.5
|
||||||
|
1.125 0.375
|
||||||
|
1.25 0.375
|
||||||
|
0.625 0.5
|
||||||
|
0.875 0.5
|
||||||
|
0.875 0.375
|
||||||
|
0.75 0.375
|
||||||
|
1.5 1.375
|
||||||
|
1.5 1.125
|
||||||
|
1.625 1.125
|
||||||
|
1.625 1.25
|
||||||
|
1.5 0.625
|
||||||
|
1.5 0.875
|
||||||
|
1.625 0.875
|
||||||
|
1.625 0.75
|
||||||
|
1.375 0.625
|
||||||
|
1.125 0.625
|
||||||
|
1.375 0.875
|
||||||
|
1.125 0.75
|
||||||
|
1.25 0.875
|
||||||
|
1.25 0.625
|
||||||
|
1.375 0.75
|
||||||
|
0.5 1.375
|
||||||
|
0.5 1.125
|
||||||
|
0.375 1.125
|
||||||
|
0.375 1.25
|
||||||
|
0.5 0.625
|
||||||
|
0.5 0.875
|
||||||
|
0.375 0.875
|
||||||
|
0.375 0.75
|
||||||
|
0.625 0.625
|
||||||
|
0.875 0.625
|
||||||
|
0.625 0.875
|
||||||
|
0.75 0.875
|
||||||
|
0.875 0.75
|
||||||
|
0.75 0.625
|
||||||
|
0.625 0.75
|
||||||
|
1.375 1.5
|
||||||
|
1.125 1.5
|
||||||
|
1.125 1.625
|
||||||
|
1.25 1.625
|
||||||
|
1.375 1.375
|
||||||
|
0.625 1.5
|
||||||
|
0.875 1.5
|
||||||
|
0.875 1.625
|
||||||
|
0.75 1.625
|
||||||
|
0.625 1.375
|
||||||
|
1.375 1.125
|
||||||
|
1.125 1.375
|
||||||
|
1.125 1.25
|
||||||
|
1.25 1.125
|
||||||
|
1.375 1.25
|
||||||
|
1.25 1.375
|
||||||
|
0.625 1.125
|
||||||
|
0.875 1.375
|
||||||
|
0.75 1.125
|
||||||
|
0.875 1.25
|
||||||
|
0.625 1.25
|
||||||
|
0.75 1.375
|
||||||
|
4 61 145
|
||||||
|
1 58 136
|
||||||
|
13 141 154
|
||||||
|
17 205 81
|
||||||
|
16 183 76
|
||||||
|
8 67 116
|
||||||
|
10 99 188
|
||||||
|
2 62 122
|
||||||
|
9 69 102
|
||||||
|
6 68 94
|
||||||
|
7 66 112
|
||||||
|
17 199 189
|
||||||
|
5 63 126
|
||||||
|
12 132 162
|
||||||
|
11 109 173
|
||||||
|
6 94 64
|
||||||
|
2 122 59
|
||||||
|
7 112 89
|
||||||
|
15 168 163
|
||||||
|
14 167 70
|
||||||
|
4 145 88
|
||||||
|
14 182 155
|
||||||
|
15 198 71
|
||||||
|
16 204 174
|
||||||
|
21 77 139
|
||||||
|
18 74 142
|
||||||
|
44 140 143
|
||||||
|
57 204 206
|
||||||
|
53 182 185
|
||||||
|
27 83 110
|
||||||
|
35 98 101
|
||||||
|
22 78 128
|
||||||
|
29 85 100
|
||||||
|
28 84 104
|
||||||
|
26 82 118
|
||||||
|
56 198 202
|
||||||
|
23 79 133
|
||||||
|
42 131 134
|
||||||
|
37 108 111
|
||||||
|
34 95 161
|
||||||
|
40 123 153
|
||||||
|
38 113 196
|
||||||
|
50 167 171
|
||||||
|
50 168 170
|
||||||
|
45 146 180
|
||||||
|
53 183 187
|
||||||
|
56 199 200
|
||||||
|
57 205 209
|
||||||
|
45 149 146
|
||||||
|
43 144 137
|
||||||
|
47 156 155
|
||||||
|
25 90 65
|
||||||
|
20 91 60
|
||||||
|
39 120 117
|
||||||
|
54 190 189
|
||||||
|
40 130 123
|
||||||
|
36 107 103
|
||||||
|
34 106 95
|
||||||
|
38 121 113
|
||||||
|
54 192 188
|
||||||
|
41 135 127
|
||||||
|
49 164 163
|
||||||
|
51 175 174
|
||||||
|
24 160 80
|
||||||
|
19 152 75
|
||||||
|
33 195 73
|
||||||
|
49 166 162
|
||||||
|
30 93 86
|
||||||
|
32 179 72
|
||||||
|
47 181 154
|
||||||
|
31 92 87
|
||||||
|
51 197 173
|
||||||
|
43 149 139
|
||||||
|
44 144 142
|
||||||
|
19 156 143
|
||||||
|
20 90 206
|
||||||
|
30 91 185
|
||||||
|
37 120 110
|
||||||
|
33 190 101
|
||||||
|
41 130 128
|
||||||
|
35 107 100
|
||||||
|
36 106 104
|
||||||
|
39 121 118
|
||||||
|
48 192 202
|
||||||
|
42 135 133
|
||||||
|
24 164 134
|
||||||
|
32 175 111
|
||||||
|
48 160 161
|
||||||
|
46 152 153
|
||||||
|
55 195 196
|
||||||
|
46 166 171
|
||||||
|
31 93 170
|
||||||
|
52 179 180
|
||||||
|
52 181 187
|
||||||
|
25 92 200
|
||||||
|
55 197 209
|
||||||
|
21 147 61
|
||||||
|
18 138 58
|
||||||
|
44 157 141
|
||||||
|
57 207 205
|
||||||
|
53 184 183
|
||||||
|
27 119 67
|
||||||
|
35 191 99
|
||||||
|
22 125 62
|
||||||
|
29 105 69
|
||||||
|
28 97 68
|
||||||
|
26 114 66
|
||||||
|
56 203 199
|
||||||
|
23 129 63
|
||||||
|
42 165 132
|
||||||
|
37 176 109
|
||||||
|
34 96 94
|
||||||
|
40 124 122
|
||||||
|
38 115 112
|
||||||
|
50 172 168
|
||||||
|
50 169 167
|
||||||
|
45 148 145
|
||||||
|
53 186 182
|
||||||
|
56 201 198
|
||||||
|
57 208 204
|
||||||
|
1 136 77
|
||||||
|
2 140 74
|
||||||
|
2 59 140
|
||||||
|
16 76 204
|
||||||
|
14 70 182
|
||||||
|
4 108 83
|
||||||
|
7 89 98
|
||||||
|
5 126 78
|
||||||
|
7 98 85
|
||||||
|
9 102 84
|
||||||
|
8 116 82
|
||||||
|
15 159 198
|
||||||
|
6 131 79
|
||||||
|
6 64 131
|
||||||
|
4 88 108
|
||||||
|
10 158 95
|
||||||
|
12 150 123
|
||||||
|
11 193 113
|
||||||
|
14 151 167
|
||||||
|
15 71 168
|
||||||
|
13 177 146
|
||||||
|
16 178 183
|
||||||
|
17 81 199
|
||||||
|
17 194 205
|
||||||
|
43 137 149
|
||||||
|
44 141 144
|
||||||
|
19 75 156
|
||||||
|
20 60 90
|
||||||
|
30 86 91
|
||||||
|
37 109 120
|
||||||
|
33 73 190
|
||||||
|
41 127 130
|
||||||
|
35 99 107
|
||||||
|
36 103 106
|
||||||
|
39 117 121
|
||||||
|
48 158 192
|
||||||
|
42 132 135
|
||||||
|
24 80 164
|
||||||
|
32 72 175
|
||||||
|
48 159 160
|
||||||
|
46 151 152
|
||||||
|
55 194 195
|
||||||
|
46 150 166
|
||||||
|
31 87 93
|
||||||
|
52 178 179
|
||||||
|
52 177 181
|
||||||
|
25 65 92
|
||||||
|
55 193 197
|
||||||
|
45 147 149
|
||||||
|
43 138 144
|
||||||
|
47 157 156
|
||||||
|
25 207 90
|
||||||
|
20 184 91
|
||||||
|
39 119 120
|
||||||
|
54 191 190
|
||||||
|
40 125 130
|
||||||
|
36 105 107
|
||||||
|
34 97 106
|
||||||
|
38 114 121
|
||||||
|
54 203 192
|
||||||
|
41 129 135
|
||||||
|
49 165 164
|
||||||
|
51 176 175
|
||||||
|
24 96 160
|
||||||
|
19 124 152
|
||||||
|
33 115 195
|
||||||
|
49 172 166
|
||||||
|
30 169 93
|
||||||
|
32 148 179
|
||||||
|
47 186 181
|
||||||
|
31 201 92
|
||||||
|
51 208 197
|
||||||
|
45 145 147
|
||||||
|
43 136 138
|
||||||
|
47 154 157
|
||||||
|
25 81 207
|
||||||
|
20 76 184
|
||||||
|
39 116 119
|
||||||
|
54 188 191
|
||||||
|
40 122 125
|
||||||
|
36 102 105
|
||||||
|
34 94 97
|
||||||
|
38 112 114
|
||||||
|
54 189 203
|
||||||
|
41 126 129
|
||||||
|
49 162 165
|
||||||
|
51 173 176
|
||||||
|
24 64 96
|
||||||
|
19 59 124
|
||||||
|
33 89 115
|
||||||
|
49 163 172
|
||||||
|
30 70 169
|
||||||
|
32 88 148
|
||||||
|
47 155 186
|
||||||
|
31 71 201
|
||||||
|
51 174 208
|
||||||
|
43 139 136
|
||||||
|
44 142 140
|
||||||
|
19 143 59
|
||||||
|
20 206 76
|
||||||
|
30 185 70
|
||||||
|
37 110 108
|
||||||
|
33 101 89
|
||||||
|
41 128 126
|
||||||
|
35 100 98
|
||||||
|
36 104 102
|
||||||
|
39 118 116
|
||||||
|
48 202 159
|
||||||
|
42 133 131
|
||||||
|
24 134 64
|
||||||
|
32 111 88
|
||||||
|
48 161 158
|
||||||
|
46 153 150
|
||||||
|
55 196 193
|
||||||
|
46 171 151
|
||||||
|
31 170 71
|
||||||
|
52 180 177
|
||||||
|
52 187 178
|
||||||
|
25 200 81
|
||||||
|
55 209 194
|
||||||
|
13 146 137
|
||||||
|
13 137 141
|
||||||
|
14 155 75
|
||||||
|
3 65 60
|
||||||
|
3 60 86
|
||||||
|
11 117 109
|
||||||
|
17 189 73
|
||||||
|
12 123 127
|
||||||
|
10 103 99
|
||||||
|
10 95 103
|
||||||
|
11 113 117
|
||||||
|
10 188 158
|
||||||
|
12 127 132
|
||||||
|
15 163 80
|
||||||
|
16 174 72
|
||||||
|
15 80 159
|
||||||
|
14 75 151
|
||||||
|
17 73 194
|
||||||
|
12 162 150
|
||||||
|
3 86 87
|
||||||
|
16 72 178
|
||||||
|
13 154 177
|
||||||
|
3 87 65
|
||||||
|
11 173 193
|
||||||
|
21 139 147
|
||||||
|
18 142 138
|
||||||
|
44 143 157
|
||||||
|
57 206 207
|
||||||
|
53 185 184
|
||||||
|
27 110 119
|
||||||
|
35 101 191
|
||||||
|
22 128 125
|
||||||
|
29 100 105
|
||||||
|
28 104 97
|
||||||
|
26 118 114
|
||||||
|
56 202 203
|
||||||
|
23 133 129
|
||||||
|
42 134 165
|
||||||
|
37 111 176
|
||||||
|
34 161 96
|
||||||
|
40 153 124
|
||||||
|
38 196 115
|
||||||
|
50 171 172
|
||||||
|
50 170 169
|
||||||
|
45 180 148
|
||||||
|
53 187 186
|
||||||
|
56 200 201
|
||||||
|
57 209 208
|
||||||
|
147 145 61
|
||||||
|
138 136 58
|
||||||
|
157 154 141
|
||||||
|
207 81 205
|
||||||
|
184 76 183
|
||||||
|
119 116 67
|
||||||
|
191 188 99
|
||||||
|
125 122 62
|
||||||
|
105 102 69
|
||||||
|
97 94 68
|
||||||
|
114 112 66
|
||||||
|
203 189 199
|
||||||
|
129 126 63
|
||||||
|
165 162 132
|
||||||
|
176 173 109
|
||||||
|
96 64 94
|
||||||
|
124 59 122
|
||||||
|
115 89 112
|
||||||
|
172 163 168
|
||||||
|
169 70 167
|
||||||
|
148 88 145
|
||||||
|
186 155 182
|
||||||
|
201 71 198
|
||||||
|
208 174 204
|
||||||
|
136 139 77
|
||||||
|
140 142 74
|
||||||
|
59 143 140
|
||||||
|
76 206 204
|
||||||
|
70 185 182
|
||||||
|
108 110 83
|
||||||
|
89 101 98
|
||||||
|
126 128 78
|
||||||
|
98 100 85
|
||||||
|
102 104 84
|
||||||
|
116 118 82
|
||||||
|
159 202 198
|
||||||
|
131 133 79
|
||||||
|
64 134 131
|
||||||
|
88 111 108
|
||||||
|
158 161 95
|
||||||
|
150 153 123
|
||||||
|
193 196 113
|
||||||
|
151 171 167
|
||||||
|
71 170 168
|
||||||
|
177 180 146
|
||||||
|
178 187 183
|
||||||
|
81 200 199
|
||||||
|
194 209 205
|
||||||
|
137 146 149
|
||||||
|
141 137 144
|
||||||
|
75 155 156
|
||||||
|
60 65 90
|
||||||
|
86 60 91
|
||||||
|
109 117 120
|
||||||
|
73 189 190
|
||||||
|
127 123 130
|
||||||
|
99 103 107
|
||||||
|
103 95 106
|
||||||
|
117 113 121
|
||||||
|
158 188 192
|
||||||
|
132 127 135
|
||||||
|
80 163 164
|
||||||
|
72 174 175
|
||||||
|
159 80 160
|
||||||
|
151 75 152
|
||||||
|
194 73 195
|
||||||
|
150 162 166
|
||||||
|
87 86 93
|
||||||
|
178 72 179
|
||||||
|
177 154 181
|
||||||
|
65 87 92
|
||||||
|
193 173 197
|
||||||
|
147 139 149
|
||||||
|
138 142 144
|
||||||
|
157 143 156
|
||||||
|
207 206 90
|
||||||
|
184 185 91
|
||||||
|
119 110 120
|
||||||
|
191 101 190
|
||||||
|
125 128 130
|
||||||
|
105 100 107
|
||||||
|
97 104 106
|
||||||
|
114 118 121
|
||||||
|
203 202 192
|
||||||
|
129 133 135
|
||||||
|
165 134 164
|
||||||
|
176 111 175
|
||||||
|
96 161 160
|
||||||
|
124 153 152
|
||||||
|
115 196 195
|
||||||
|
172 171 166
|
||||||
|
169 170 93
|
||||||
|
148 180 179
|
||||||
|
186 187 181
|
||||||
|
201 200 92
|
||||||
|
208 209 197
|
||||||
|
64
|
||||||
|
1 58
|
||||||
|
2 59
|
||||||
|
3 60
|
||||||
|
4 61
|
||||||
|
2 62
|
||||||
|
5 63
|
||||||
|
6 64
|
||||||
|
3 65
|
||||||
|
7 66
|
||||||
|
8 67
|
||||||
|
6 68
|
||||||
|
9 69
|
||||||
|
14 70
|
||||||
|
15 71
|
||||||
|
16 72
|
||||||
|
17 73
|
||||||
|
18 74
|
||||||
|
19 75
|
||||||
|
20 76
|
||||||
|
21 77
|
||||||
|
22 78
|
||||||
|
23 79
|
||||||
|
24 80
|
||||||
|
25 81
|
||||||
|
26 82
|
||||||
|
27 83
|
||||||
|
28 84
|
||||||
|
29 85
|
||||||
|
30 86
|
||||||
|
31 87
|
||||||
|
32 88
|
||||||
|
33 89
|
||||||
|
58 18
|
||||||
|
59 19
|
||||||
|
60 20
|
||||||
|
61 21
|
||||||
|
62 22
|
||||||
|
63 23
|
||||||
|
64 24
|
||||||
|
65 25
|
||||||
|
66 26
|
||||||
|
67 27
|
||||||
|
68 28
|
||||||
|
69 29
|
||||||
|
70 30
|
||||||
|
71 31
|
||||||
|
72 32
|
||||||
|
73 33
|
||||||
|
74 2
|
||||||
|
75 14
|
||||||
|
76 16
|
||||||
|
77 1
|
||||||
|
78 5
|
||||||
|
79 6
|
||||||
|
80 15
|
||||||
|
81 17
|
||||||
|
82 8
|
||||||
|
83 4
|
||||||
|
84 9
|
||||||
|
85 7
|
||||||
|
86 3
|
||||||
|
87 3
|
||||||
|
88 4
|
||||||
|
89 7
|
||||||
|
1 0
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
1 0
|
||||||
|
2 0
|
||||||
|
2 0
|
||||||
|
2 4
|
||||||
|
3 4
|
||||||
|
3 0
|
||||||
|
3 0
|
||||||
|
4 0
|
||||||
|
4 0
|
||||||
|
1 2
|
||||||
|
2 4
|
||||||
|
1 3
|
||||||
|
3 4
|
||||||
|
1 0
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
1 0
|
||||||
|
2 0
|
||||||
|
2 0
|
||||||
|
2 4
|
||||||
|
3 4
|
||||||
|
3 0
|
||||||
|
3 0
|
||||||
|
4 0
|
||||||
|
4 0
|
||||||
|
1 2
|
||||||
|
2 4
|
||||||
|
1 3
|
||||||
|
3 4
|
||||||
|
1 0
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
1 0
|
||||||
|
2 0
|
||||||
|
2 0
|
||||||
|
2 4
|
||||||
|
3 4
|
||||||
|
3 0
|
||||||
|
3 0
|
||||||
|
4 0
|
||||||
|
4 0
|
||||||
|
1 2
|
||||||
|
2 4
|
||||||
|
1 3
|
||||||
|
3 4
|
||||||
|
1 0
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
1 0
|
||||||
|
2 0
|
||||||
|
2 0
|
||||||
|
2 4
|
||||||
|
3 4
|
||||||
|
3 0
|
||||||
|
3 0
|
||||||
|
4 0
|
||||||
|
4 0
|
||||||
|
1 2
|
||||||
|
2 4
|
||||||
|
1 3
|
||||||
|
3 4
|
||||||
385
sheet7/jacobi.template/square_bb_4_sd.txt
Normal file
385
sheet7/jacobi.template/square_bb_4_sd.txt
Normal file
|
|
@ -0,0 +1,385 @@
|
||||||
|
384
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
3
|
||||||
|
1
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
4
|
||||||
|
4
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
BIN
sheet7/jacobi.template/square_tiny.pdf
Normal file
BIN
sheet7/jacobi.template/square_tiny.pdf
Normal file
Binary file not shown.
95
sheet7/jacobi.template/square_tiny.txt
Normal file
95
sheet7/jacobi.template/square_tiny.txt
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
13
|
||||||
|
2
|
||||||
|
16
|
||||||
|
3
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0.5
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0.5
|
||||||
|
0.4999999999999999
|
||||||
|
0.4999999999999999
|
||||||
|
0.3333333333333333
|
||||||
|
0.6666666666666666
|
||||||
|
0.6666666666666666
|
||||||
|
0.6666666666666666
|
||||||
|
0.6666666666666666
|
||||||
|
0.3333333333333333
|
||||||
|
0.3333333333333333
|
||||||
|
0.3333333333333333
|
||||||
|
8
|
||||||
|
1
|
||||||
|
13
|
||||||
|
5
|
||||||
|
2
|
||||||
|
12
|
||||||
|
6
|
||||||
|
3
|
||||||
|
11
|
||||||
|
7
|
||||||
|
4
|
||||||
|
10
|
||||||
|
1
|
||||||
|
5
|
||||||
|
13
|
||||||
|
10
|
||||||
|
8
|
||||||
|
13
|
||||||
|
2
|
||||||
|
6
|
||||||
|
12
|
||||||
|
3
|
||||||
|
7
|
||||||
|
11
|
||||||
|
4
|
||||||
|
8
|
||||||
|
10
|
||||||
|
12
|
||||||
|
9
|
||||||
|
13
|
||||||
|
10
|
||||||
|
9
|
||||||
|
11
|
||||||
|
7
|
||||||
|
10
|
||||||
|
11
|
||||||
|
11
|
||||||
|
9
|
||||||
|
12
|
||||||
|
6
|
||||||
|
11
|
||||||
|
12
|
||||||
|
9
|
||||||
|
10
|
||||||
|
13
|
||||||
|
5
|
||||||
|
12
|
||||||
|
13
|
||||||
|
8
|
||||||
|
1
|
||||||
|
5
|
||||||
|
5
|
||||||
|
2
|
||||||
|
2
|
||||||
|
6
|
||||||
|
6
|
||||||
|
3
|
||||||
|
3
|
||||||
|
7
|
||||||
|
7
|
||||||
|
4
|
||||||
|
4
|
||||||
|
8
|
||||||
|
8
|
||||||
|
1
|
||||||
16
sheet7/jacobi.template/userset.cpp
Normal file
16
sheet7/jacobi.template/userset.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include "userset.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
double FunctF(double const x , double const y)
|
||||||
|
{
|
||||||
|
// return std::sin(3.14159*1*x)*std::sin(3.14159*1*y);
|
||||||
|
// return 16.0*1024. ;
|
||||||
|
// return (double)1.0 ;
|
||||||
|
return x * x * std::sin(2.5 * 3.14159 * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double FunctU(const double /* x */, double const /* y */)
|
||||||
|
{
|
||||||
|
return 1.0 ;
|
||||||
|
}
|
||||||
47
sheet7/jacobi.template/userset.h
Normal file
47
sheet7/jacobi.template/userset.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef USERSET_FILE
|
||||||
|
#define USERSET_FILE
|
||||||
|
#include <cmath>
|
||||||
|
/**
|
||||||
|
* User function: f(@p x,@p y)
|
||||||
|
* @param[in] x x-coordinate of discretization point
|
||||||
|
* @param[in] y y-coordinate of discretization point
|
||||||
|
* @return value for right hand side f(@p x,@p y)
|
||||||
|
*/
|
||||||
|
double FunctF(double const x, double const y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User function: u(@p x,@p y)
|
||||||
|
* @param[in] x x-coordinate of discretization point
|
||||||
|
* @param[in] y y-coordinate of discretization point
|
||||||
|
* @return value for solution vector u(@p x,@p y)
|
||||||
|
*/
|
||||||
|
double FunctU(double const x, double const y);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User function: f(@p x,@p y) = @f$ x^2 \sin(2.5\pi y)@f$.
|
||||||
|
* @param[in] x x-coordinate of discretization point
|
||||||
|
* @param[in] y y-coordinate of discretization point
|
||||||
|
* @return value f(@p x,@p y)
|
||||||
|
*/
|
||||||
|
inline
|
||||||
|
double fNice(double const x, double const y)
|
||||||
|
{
|
||||||
|
//return x * x * std::sin(2.5 * M_PI * y); // solution u
|
||||||
|
return std::sin(M_PI*2.5*y)*(M_PI*M_PI*2.5*2.5*x*x - 2); // -Laplacian(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User function: f(@p x,@p y) = 0$.
|
||||||
|
* @param[in] x x-coordinate of discretization point
|
||||||
|
* @param[in] y y-coordinate of discretization point
|
||||||
|
* @return value 0
|
||||||
|
*/
|
||||||
|
inline
|
||||||
|
double f_zero(double const x, double const y)
|
||||||
|
//double f_zero(double const /*x*/, double const /*y*/)
|
||||||
|
{
|
||||||
|
return 0.0 + 0.0*(x+y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
122
sheet7/jacobi.template/vdop.cpp
Normal file
122
sheet7/jacobi.template/vdop.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
#include "vdop.h"
|
||||||
|
#include <cassert> // assert()
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
void vddiv(vector<double> & x, vector<double> const& y,
|
||||||
|
vector<double> const& z)
|
||||||
|
{
|
||||||
|
assert( x.size()==y.size() && y.size()==z.size() );
|
||||||
|
size_t n = x.size();
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (size_t k = 0; k < n; ++k)
|
||||||
|
{
|
||||||
|
x[k] = y[k] / z[k];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
|
||||||
|
void vdaxpy(std::vector<double> & x, std::vector<double> const& y,
|
||||||
|
double alpha, std::vector<double> const& z )
|
||||||
|
{
|
||||||
|
assert( x.size()==y.size() && y.size()==z.size() );
|
||||||
|
size_t n = x.size();
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (size_t k = 0; k < n; ++k)
|
||||||
|
{
|
||||||
|
x[k] = y[k] + alpha * z[k];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//******************************************************************************
|
||||||
|
|
||||||
|
double dscapr(std::vector<double> const& x, std::vector<double> const& y)
|
||||||
|
{
|
||||||
|
assert( x.size()==y.size());
|
||||||
|
size_t n = x.size();
|
||||||
|
|
||||||
|
double s = 0.0;
|
||||||
|
#pragma omp parallel for reduction(+:s)
|
||||||
|
for (size_t k = 0; k < n; ++k)
|
||||||
|
{
|
||||||
|
s += x[k] * y[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
bool CompareVectors(std::vector<double> const& x, int const n, double const y[], double const eps)
|
||||||
|
{
|
||||||
|
bool bn = (static_cast<int>(x.size())==n);
|
||||||
|
if (!bn)
|
||||||
|
{
|
||||||
|
cout << "######### Error: " << "number of elements" << endl;
|
||||||
|
}
|
||||||
|
//bool bv = equal(x.cbegin(),x.cend(),y);
|
||||||
|
bool bv = equal(x.cbegin(),x.cend(),y,
|
||||||
|
[eps](double a, double b) -> bool
|
||||||
|
{ return std::abs(a-b)<eps*(1.0+0.5*(std::abs(a)+ std::abs(b))); }
|
||||||
|
);
|
||||||
|
if (!bv)
|
||||||
|
{
|
||||||
|
assert(static_cast<int>(x.size())==n);
|
||||||
|
cout << "######### Error: " << "values" << endl;
|
||||||
|
}
|
||||||
|
return bn && bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
double par_scalar(vector<double> const &x, vector<double> const &y, MPI_Comm const& icomm)
|
||||||
|
{
|
||||||
|
const double s = dscapr(x,y);
|
||||||
|
double sg;
|
||||||
|
MPI_Allreduce(&s,&sg,1,MPI_DOUBLE,MPI_SUM,icomm);
|
||||||
|
|
||||||
|
return(sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
void ExchangeAll(vector<double> const &xin, vector<double> &yout, MPI_Comm const &icomm)
|
||||||
|
{
|
||||||
|
int myrank, numprocs,ierr(-1);
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
int const N=xin.size();
|
||||||
|
int const sendcount = N/numprocs; // equal sized junks
|
||||||
|
assert(sendcount*numprocs==N); // really all junk sized?
|
||||||
|
assert(xin.size()==yout.size());
|
||||||
|
|
||||||
|
auto sendbuf = xin.data();
|
||||||
|
auto recvbuf = yout.data();
|
||||||
|
ierr = MPI_Alltoall(sendbuf, sendcount, MPI_DOUBLE,
|
||||||
|
recvbuf, sendcount, MPI_DOUBLE, icomm);
|
||||||
|
assert(0==ierr);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
void ExchangeAllInPlace(vector<double> &xin, MPI_Comm const &icomm)
|
||||||
|
{
|
||||||
|
int myrank, numprocs,ierr(-1);
|
||||||
|
MPI_Comm_rank(icomm, &myrank); // my MPI-rank
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
int const N=xin.size();
|
||||||
|
int const sendcount = N/numprocs; // equal sized junks
|
||||||
|
assert(sendcount*numprocs==N); // really all junk sized?
|
||||||
|
|
||||||
|
auto sendbuf = xin.data();
|
||||||
|
ierr = MPI_Alltoall(MPI_IN_PLACE, sendcount, MPI_DOUBLE,
|
||||||
|
sendbuf, sendcount, MPI_DOUBLE, icomm);
|
||||||
|
assert(0==ierr);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
167
sheet7/jacobi.template/vdop.h
Normal file
167
sheet7/jacobi.template/vdop.h
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
#ifndef VDOP_FILE
|
||||||
|
#define VDOP_FILE
|
||||||
|
#include <iostream>
|
||||||
|
#include <mpi.h> // MPI
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/** @brief Element-wise vector divison x_k = y_k/z_k.
|
||||||
|
*
|
||||||
|
* @param[out] x target vector
|
||||||
|
* @param[in] y source vector
|
||||||
|
* @param[in] z source vector
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void vddiv(std::vector<double> &x, std::vector<double> const &y,
|
||||||
|
std::vector<double> const &z);
|
||||||
|
|
||||||
|
/** @brief Element-wise daxpy operation x(k) = y(k) + alpha*z(k).
|
||||||
|
*
|
||||||
|
* @param[out] x target vector
|
||||||
|
* @param[in] y source vector
|
||||||
|
* @param[in] alpha scalar
|
||||||
|
* @param[in] z source vector
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void vdaxpy(std::vector<double> &x, std::vector<double> const &y,
|
||||||
|
double alpha, std::vector<double> const &z );
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Calculates the Euclidean inner product of two vectors.
|
||||||
|
*
|
||||||
|
* @param[in] x vector
|
||||||
|
* @param[in] y vector
|
||||||
|
* @return Euclidean inner product @f$\langle x,y \rangle@f$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
double dscapr(std::vector<double> const &x, std::vector<double> const &y);
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
double L2_scapr(std::vector<double> const &x, std::vector<double> const &y)
|
||||||
|
{
|
||||||
|
return dscapr(x, y) / x.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Parallel inner product
|
||||||
|
@param[in] x vector
|
||||||
|
@param[in] y vector
|
||||||
|
@param[in] icomm MPI communicator
|
||||||
|
@return resulting Euclidian inner product <x,y>
|
||||||
|
*/
|
||||||
|
double par_scalar(std::vector<double> const &x, std::vector<double> const &y,
|
||||||
|
MPI_Comm const& icomm=MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ReadId : Input and broadcast of an integer */
|
||||||
|
inline
|
||||||
|
int ReadIn(std::string const &ss = std::string(), MPI_Comm const &icomm = MPI_COMM_WORLD)
|
||||||
|
{
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
int myrank; /* my rank number */
|
||||||
|
MPI_Comm_rank(icomm, &myrank);
|
||||||
|
int id;
|
||||||
|
|
||||||
|
if (myrank == 0) {
|
||||||
|
std::cout << "\n\n " << ss << " : Which process do you want to debug ? \n";
|
||||||
|
std::cin >> id;
|
||||||
|
}
|
||||||
|
MPI_Bcast(&id, 1, MPI_INT, 0, icomm);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print entries of a vector to standard output.
|
||||||
|
*
|
||||||
|
* @param[in] v vector values
|
||||||
|
* @param[in] ss string containing the vector name
|
||||||
|
* @param[in] icomm communicator group for MPI
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
void DebugVector(std::vector<T> const &v, std::string const &ss = std::string(), MPI_Comm const &icomm = MPI_COMM_WORLD)
|
||||||
|
{
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
std::cout.flush();
|
||||||
|
int numprocs; /* # processes */
|
||||||
|
MPI_Comm_size(icomm, &numprocs);
|
||||||
|
int myrank; /* my rank number */
|
||||||
|
MPI_Comm_rank(icomm, &myrank);
|
||||||
|
|
||||||
|
int readid = ReadIn(ss); /* Read readid */
|
||||||
|
|
||||||
|
while ( (0 <= readid) && (readid < numprocs) ) {
|
||||||
|
if (myrank == readid) {
|
||||||
|
std::cout << "\n\n process " << readid;
|
||||||
|
std::cout << "\n .... " << ss << " (nnode = " << v.size() << ")\n";
|
||||||
|
for (size_t j = 0; j < v.size(); ++j) {
|
||||||
|
std::cout.setf(std::ios::right, std::ios::adjustfield);
|
||||||
|
std::cout << "[" << j << "] "<< v[j] << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
readid = ReadIn(ss, icomm); /* Read readid */
|
||||||
|
}
|
||||||
|
MPI_Barrier(icomm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Compares an STL vector with POD vector.
|
||||||
|
*
|
||||||
|
* The accuracy criteria @f$ |x_k-y_k| < \varepsilon \left({1+0.5(|x_k|+|y_k|)}\right) @f$
|
||||||
|
* follows the book by
|
||||||
|
* <a href="https://www.springer.com/la/book/9783319446592">Stoyan/Baran</a>, p.8.
|
||||||
|
*
|
||||||
|
* @param[in] x STL vector
|
||||||
|
* @param[in] n length of POD vector
|
||||||
|
* @param[in] y POD vector
|
||||||
|
* @param[in] eps relative accuracy criteria (default := 0.0).
|
||||||
|
* @return true iff pairwise vector elements are relatively close to each other.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool CompareVectors(std::vector<double> const &x, int n, double const y[], double const eps = 0.0);
|
||||||
|
|
||||||
|
|
||||||
|
/** Output operator for vector
|
||||||
|
* @param[in,out] s output stream, e.g. @p cout
|
||||||
|
* @param[in] v vector
|
||||||
|
*
|
||||||
|
* @return output stream
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
std::ostream& operator<<(std::ostream &s, std::vector<T> const &v)
|
||||||
|
{
|
||||||
|
for (auto vp: v)
|
||||||
|
{
|
||||||
|
s << vp << " ";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Exchanges equal size partions of vector @p xin with all MPI processes.
|
||||||
|
* The received data are return in vector @p yout .
|
||||||
|
*
|
||||||
|
* @param[in] xin input vector
|
||||||
|
* @param[out] yout output vector
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ExchangeAll(std::vector<double> const &xin, std::vector<double> &yout, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
/** Exchanges equal size partions of vector @p xin with all MPI processes.
|
||||||
|
* The received data are return in vector @p xin .
|
||||||
|
*
|
||||||
|
* @param[in,out] xin input/output vector
|
||||||
|
* @param[in] icomm MPI communicator
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ExchangeAllInPlace(std::vector<double> &xin, MPI_Comm const &icomm = MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
52
sheet7/jacobi.template/visualize_par_results.m
Normal file
52
sheet7/jacobi.template/visualize_par_results.m
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
%% Visualize results
|
||||||
|
%
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
%
|
||||||
|
% or
|
||||||
|
%
|
||||||
|
% matlab -nosplash -nodesktop -r 'try visualize_par_results(4); catch; end; quit'
|
||||||
|
%
|
||||||
|
function visualize_par_results(nprocs)
|
||||||
|
%%
|
||||||
|
if nargin<1
|
||||||
|
nprocs = 4;
|
||||||
|
end
|
||||||
|
fprintf('# procs = %d\n',nprocs)
|
||||||
|
|
||||||
|
pre = 'uv_';
|
||||||
|
post = '.txt';
|
||||||
|
|
||||||
|
xc = []; nnodes = [];
|
||||||
|
ia = []; nelems = [];
|
||||||
|
v = [];
|
||||||
|
node_offset = 0;
|
||||||
|
elem_offset = 0;
|
||||||
|
for rank=0:nprocs-1
|
||||||
|
fname = [pre,num2str(rank,'%2u'),post];
|
||||||
|
[lxc,lia,lv] = ascii_read_meshvector(fname);
|
||||||
|
% whos lxc lia lv
|
||||||
|
nnodes = [nnodes size(lxc,1)];
|
||||||
|
nelems = [nelems size(lia,1)];
|
||||||
|
%[xc,ia,v]
|
||||||
|
xc = [xc; lxc];
|
||||||
|
v = [v ; lv ];
|
||||||
|
ia = [ia; lia+node_offset];
|
||||||
|
% node_offset
|
||||||
|
% lia = lia + node_offset
|
||||||
|
% ia = [ia; lia];
|
||||||
|
% index offsets for next subdomain
|
||||||
|
node_offset = node_offset + nnodes(end);
|
||||||
|
elem_offset = elem_offset + nelems(end);
|
||||||
|
end
|
||||||
|
|
||||||
|
% fname = 'uv.txt';
|
||||||
|
% [xc,ia,v] = ascii_read_meshvector(fname);
|
||||||
|
|
||||||
|
h = trisurf(ia, xc(:,1), xc(:,2), v);
|
||||||
|
xlabel('x'),ylabel('y'),zlabel('z')
|
||||||
|
|
||||||
|
shading interp
|
||||||
|
|
||||||
|
waitfor(h) % wait for closing the figure
|
||||||
20
sheet7/jacobi.template/visualize_results.m
Normal file
20
sheet7/jacobi.template/visualize_results.m
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
%% Visualize results
|
||||||
|
%
|
||||||
|
% flatpak run org.octave.Octave <filename>
|
||||||
|
% or
|
||||||
|
% octave --no-window-system --no-gui -qf <filename>
|
||||||
|
%
|
||||||
|
% or
|
||||||
|
% matlab -nosplash < <filename>
|
||||||
|
|
||||||
|
clear all
|
||||||
|
clc
|
||||||
|
|
||||||
|
%%
|
||||||
|
fname = 'uv.txt';
|
||||||
|
|
||||||
|
[xc,ia,v] = ascii_read_meshvector(fname);
|
||||||
|
|
||||||
|
h = trisurf(ia, xc(:,1), xc(:,2), v);
|
||||||
|
|
||||||
|
waitfor(h) % wait for closing the figure
|
||||||
Loading…
Add table
Add a link
Reference in a new issue