Actual source code: network.c
slepc-main 2024-11-22
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
11: #include "network.h"
13: const char *GraphTypes[] = {"sym","asym","bip",NULL};
14: const char *GraphWeights[] = {"unweighted","positive","posweighted","signed","multisigned","weighted","multiweighted","dynamic","multiposweighted",NULL};
16: PetscErrorCode GraphCreate(MPI_Comm comm,Graph *graph)
17: {
18: PetscFunctionBeginUser;
19: PetscCall(PetscNew(graph));
20: (*graph)->comm = comm;
21: PetscFunctionReturn(PETSC_SUCCESS);
22: }
24: PetscErrorCode GraphDestroy(Graph *graph)
25: {
26: PetscFunctionBeginUser;
27: if (!*graph) PetscFunctionReturn(PETSC_SUCCESS);
28: PetscCall(MatDestroy(&((*graph)->adjacency)));
29: PetscCall(PetscFree(*graph));
30: PetscFunctionReturn(PETSC_SUCCESS);
31: }
33: PetscErrorCode GraphPreload(Graph graph,char *filename)
34: {
35: PetscInt i,nval,src,dst;
36: PetscBool flg;
37: PetscMPIInt rank;
38: FILE *file;
39: char gtype[64],gweight[64],line[PETSC_MAX_PATH_LEN];
41: PetscFunctionBeginUser;
42: PetscCallMPI(MPI_Comm_rank(graph->comm,&rank));
43: if (rank==0) {
44: PetscCall(PetscFOpen(PETSC_COMM_SELF,filename,"r",&file));
45: /* process first line of the file */
46: nval = fscanf(file,"%%%s%s\n",gtype,gweight);
47: PetscCheck(nval==2,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file");
48: for (i=0;i<(int)sizeof(GraphTypes);i++) {
49: PetscCheck(GraphTypes[i],PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Unknown graph type %s",gtype);
50: PetscCall(PetscStrcmp(gtype,GraphTypes[i],&flg));
51: if (flg) { graph->type = (GraphType)i; break; }
52: }
53: for (i=0;i<(int)sizeof(GraphWeights);i++) {
54: PetscCheck(GraphWeights[i],PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Unknown graph weight %s",gweight);
55: PetscCall(PetscStrcmp(gweight,GraphWeights[i],&flg));
56: if (flg) { graph->weight = (GraphWeight)i; break; }
57: }
58: /* skip second line of the file if it is a comment */
59: if (!fgets(line,PETSC_MAX_PATH_LEN,file)) line[0] = 0;
60: if (line[0]=='%') {
61: if (!fgets(line,PETSC_MAX_PATH_LEN,file)) line[0] = 0;
62: }
63: graph->nedges = 1;
64: nval = sscanf(line,"%" PetscInt_FMT "%" PetscInt_FMT,&src,&dst);
65: PetscCheck(nval==2,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file");
66: graph->nvertices = PetscMax(src,dst);
67: /* read rest of file to count lines */
68: while (fgets(line,PETSC_MAX_PATH_LEN,file)) {
69: nval = sscanf(line,"%" PetscInt_FMT "%" PetscInt_FMT,&src,&dst);
70: PetscCheck(nval==2,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file");
71: graph->nedges++;
72: graph->nvertices = PetscMax(graph->nvertices,PetscMax(src,dst));
73: }
74: PetscCall(PetscFClose(PETSC_COMM_SELF,file));
75: }
76: PetscCallMPI(MPI_Bcast(&graph->type,1,MPIU_INT,0,PETSC_COMM_WORLD));
77: PetscCallMPI(MPI_Bcast(&graph->weight,1,MPIU_INT,0,PETSC_COMM_WORLD));
78: PetscCallMPI(MPI_Bcast(&graph->nvertices,1,MPIU_INT,0,PETSC_COMM_WORLD));
79: PetscCallMPI(MPI_Bcast(&graph->nedges,1,MPIU_INT,0,PETSC_COMM_WORLD));
80: PetscFunctionReturn(PETSC_SUCCESS);
81: }
83: PetscErrorCode GraphPreallocate(Graph graph,char *filename)
84: {
85: PetscInt i,nval,src,dst,Istart,Iend,*d_nnz,*o_nnz;
86: FILE *file;
87: char line[PETSC_MAX_PATH_LEN];
89: PetscFunctionBeginUser;
90: PetscCheck(graph->nvertices,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call GraphPreload() first");
91: PetscCall(MatDestroy(&graph->adjacency));
92: PetscCall(MatCreate(graph->comm,&graph->adjacency));
93: PetscCall(MatSetSizes(graph->adjacency,PETSC_DECIDE,PETSC_DECIDE,graph->nvertices,graph->nvertices));
94: PetscCall(MatSetType(graph->adjacency,MATAIJ));
95: PetscCall(MatGetOwnershipRange(graph->adjacency,&Istart,&Iend));
96: PetscCall(PetscCalloc2(Iend-Istart,&d_nnz,Iend-Istart,&o_nnz));
98: /* all process read the file */
99: PetscCall(PetscFOpen(PETSC_COMM_SELF,filename,"r",&file));
100: nval = fscanf(file,"%%%*s%*s\n"); /* first line of the file */
101: if (!fgets(line,PETSC_MAX_PATH_LEN,file)) line[0] = 0;
102: if (line[0]=='%') { /* skip second line of the file if it is a comment */
103: if (!fgets(line,PETSC_MAX_PATH_LEN,file)) line[0] = 0;
104: }
105: nval = sscanf(line,"%" PetscInt_FMT "%" PetscInt_FMT,&src,&dst);
106: PetscCheck(nval==2,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file");
107: src--; dst--; /* adjust from 1-based to 0-based */
108: if (src>=Istart && src<Iend) {
109: if (dst>=Istart && dst<Iend) d_nnz[src-Istart]++;
110: else o_nnz[src-Istart]++;
111: }
112: /* read rest of file */
113: while (fgets(line,PETSC_MAX_PATH_LEN,file)) {
114: nval = sscanf(line,"%" PetscInt_FMT "%" PetscInt_FMT,&src,&dst);
115: PetscCheck(nval==2,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file");
116: src--; dst--; /* adjust from 1-based to 0-based */
117: if (src>=Istart && src<Iend) {
118: if (dst>=Istart && dst<Iend) d_nnz[src-Istart]++;
119: else o_nnz[src-Istart]++;
120: }
121: }
122: PetscCall(PetscFClose(PETSC_COMM_SELF,file));
124: for (i=Istart;i<Iend;i++) d_nnz[i-Istart]++; /* diagonal entries */
125: PetscCall(MatSeqAIJSetPreallocation(graph->adjacency,0,d_nnz));
126: PetscCall(MatMPIAIJSetPreallocation(graph->adjacency,0,d_nnz,0,o_nnz));
127: PetscCall(PetscFree2(d_nnz,o_nnz));
128: PetscFunctionReturn(PETSC_SUCCESS);
129: }
131: PetscErrorCode GraphLoadUnweighted(Graph graph,char *filename)
132: {
133: PetscInt i,nval,src,dst,Istart,Iend;
134: FILE *file;
135: char line[PETSC_MAX_PATH_LEN];
137: PetscFunctionBeginUser;
138: PetscCheck(graph->adjacency,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call GraphPreallocate() first");
139: PetscCall(MatGetOwnershipRange(graph->adjacency,&Istart,&Iend));
140: /* all process read the file */
141: PetscCall(PetscFOpen(PETSC_COMM_SELF,filename,"r",&file));
142: nval = fscanf(file,"%%%*s%*s\n"); /* first line of the file */
143: if (!fgets(line,PETSC_MAX_PATH_LEN,file)) line[0] = 0;
144: if (line[0]=='%') { /* skip second line of the file if it is a comment */
145: if (!fgets(line,PETSC_MAX_PATH_LEN,file)) line[0] = 0;
146: }
147: nval = sscanf(line,"%" PetscInt_FMT "%" PetscInt_FMT,&src,&dst);
148: PetscCheck(nval==2,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file");
149: src--; dst--; /* adjust from 1-based to 0-based */
150: if (src>=Istart && src<Iend) PetscCall(MatSetValue(graph->adjacency,src,dst,1.0,INSERT_VALUES));
151: /* read rest of file */
152: while (fgets(line,PETSC_MAX_PATH_LEN,file)) {
153: nval = sscanf(line,"%" PetscInt_FMT "%" PetscInt_FMT,&src,&dst);
154: PetscCheck(nval==2,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file");
155: src--; dst--; /* adjust from 1-based to 0-based */
156: if (src>=Istart && src<Iend) PetscCall(MatSetValue(graph->adjacency,src,dst,1.0,INSERT_VALUES));
157: }
158: PetscCall(PetscFClose(PETSC_COMM_SELF,file));
159: for (i=Istart;i<Iend;i++) PetscCall(MatSetValue(graph->adjacency,i,i,0.0,INSERT_VALUES)); /* diagonal entries */
160: PetscCall(MatAssemblyBegin(graph->adjacency,MAT_FINAL_ASSEMBLY));
161: PetscCall(MatAssemblyEnd(graph->adjacency,MAT_FINAL_ASSEMBLY));
162: PetscFunctionReturn(PETSC_SUCCESS);
163: }