|
1 |
| -#include "hiopVector.hpp" |
2 |
| -#include "hiopNlpFormulation.hpp" |
3 |
| -#include "hiopInterface.hpp" |
4 |
| -#include "hiopAlgFilterIPM.hpp" |
5 |
| - |
6 |
| -#ifdef WITH_MPI |
7 |
| -#include "mpi.h" |
8 |
| -#else |
9 |
| -#define MPI_COMM_WORLD 0 |
10 |
| -#define MPI_Comm int |
11 |
| -#endif |
| 1 | +#include "nlpDenseCons_ex1.hpp" |
12 | 2 |
|
13 | 3 | #include <cmath>
|
14 | 4 | #include <cstdio>
|
15 | 5 | #include <cassert>
|
16 | 6 |
|
17 |
| -/* Example 1: min sum{x_i^2 | i=1,..,n} s.t. x_2>=1 */ |
| 7 | +using namespace hiop; |
18 | 8 |
|
19 |
| -class Ex1Interface : public hiop::hiopInterfaceDenseConstraints |
| 9 | +Ex1Meshing1D::Ex1Meshing1D(double a, double b, |
| 10 | + long long glob_n, double r, |
| 11 | + MPI_Comm comm_) |
20 | 12 | {
|
21 |
| -public: |
22 |
| - Ex1Interface(int num_vars=4) |
23 |
| - : n_vars(num_vars), n_cons(0), comm(MPI_COMM_WORLD) |
24 |
| - { |
25 |
| - comm_size=1; my_rank=0; |
26 |
| -#ifdef WITH_MPI |
27 |
| - int ierr = MPI_Comm_size(comm, &comm_size); assert(MPI_SUCCESS==ierr); |
28 |
| - ierr = MPI_Comm_rank(comm, &my_rank); assert(MPI_SUCCESS==ierr); |
29 |
| -#endif |
30 |
| - // set up vector distribution for primal variables - easier to store it as a member in this simple example |
31 |
| - col_partition = new long long[comm_size]; |
32 |
| - long long quotient=n_vars/comm_size, remainder=n_vars-comm_size*quotient; |
33 |
| - if(my_rank==0) printf("reminder=%d quotient=%d\n", remainder, quotient); |
34 |
| - int i=0; col_partition[i]=0; i++; |
35 |
| - while(i<=remainder) { col_partition[i] = col_partition[i-1]+quotient+1; i++; } |
36 |
| - while(i<=comm_size) { col_partition[i] = col_partition[i-1]+quotient; i++; } |
37 |
| - |
38 |
| - if(my_rank==0) { |
39 |
| - for(int i=0;i<=comm_size;i++) |
40 |
| - printf("%3d ", col_partition[i]); |
41 |
| - printf("\n"); |
42 |
| - } |
43 |
| - } |
44 |
| - virtual ~Ex1Interface() |
45 |
| - { |
46 |
| - delete[] col_partition; |
47 |
| - } |
48 |
| - bool get_prob_sizes(long long& n, long long& m) |
49 |
| - { n=n_vars; m=n_cons; return true; } |
50 |
| - |
51 |
| - bool get_vars_info(const long long& n, double *xlow, double* xupp, NonlinearityType* type) |
52 |
| - { |
53 |
| - int i_local; |
54 |
| - for(int i_global=col_partition[my_rank]; i_global<col_partition[my_rank+1]; i_global++) { |
55 |
| - i_local=idx_global2local(n,i_global); |
56 |
| - if(i_global==2) xlow[i_local]= 1.0; |
57 |
| - else xlow[i_local]=-1e20; |
58 |
| - type[i_local] = hiopLinear; |
59 |
| - xupp[i_local] = 1e20; |
60 |
| - } |
61 |
| - return true; |
62 |
| - } |
63 |
| - bool get_cons_info(const long long& m, double* clow, double* cupp, NonlinearityType* type) |
64 |
| - { |
65 |
| - assert(m==n_cons); |
66 |
| - //no constraints |
67 |
| - return true; |
68 |
| - } |
69 |
| - bool eval_f(const long long& n, const double* x, bool new_x, double& obj_value) |
70 |
| - { |
71 |
| - int n_local=col_partition[my_rank+1]-col_partition[my_rank]; |
72 |
| - obj_value=0.; |
73 |
| - for(int i=0;i<n_local;i++) obj_value += x[i]*x[i]; |
| 13 | + _a=a; _b=b; _r=r; |
| 14 | + comm=comm_; |
| 15 | + comm_size=1; my_rank=0; |
74 | 16 | #ifdef WITH_MPI
|
75 |
| - double obj_global; |
76 |
| - int ierr=MPI_Allreduce(&obj_value, &obj_global, 1, MPI_DOUBLE, MPI_SUM, comm); assert(ierr==MPI_SUCCESS); |
77 |
| - obj_value=obj_global; |
| 17 | + int ierr = MPI_Comm_size(comm, &comm_size); assert(MPI_SUCCESS==ierr); |
| 18 | + ierr = MPI_Comm_rank(comm, &my_rank); assert(MPI_SUCCESS==ierr); |
78 | 19 | #endif
|
79 |
| - return true; |
80 |
| - } |
81 |
| - bool eval_grad_f(const long long& n, const double* x, bool new_x, double* gradf) |
82 |
| - { |
83 |
| - int n_local=col_partition[my_rank+1]-col_partition[my_rank]; |
84 |
| - for(int i=0;i<n_local;i++) gradf[i] = 2*x[i]; |
85 |
| - return true; |
86 |
| - } |
87 |
| - /** Sum(x[i])<=10 and sum(x[i])>= 1 (we pretend are different) |
88 |
| - */ |
89 |
| - bool eval_cons(const long long& n, |
90 |
| - const long long& m, |
91 |
| - const long long& num_cons, const long long* idx_cons, |
92 |
| - const double* x, bool new_x, double* cons) |
93 |
| - { |
94 |
| - assert(n==n_vars); assert(m==n_cons); |
95 |
| - //no constraints |
96 |
| - return true; |
97 |
| - } |
| 20 | + // set up vector distribution for primal variables - easier to store it as a member in this simple example |
| 21 | + col_partition = new long long[comm_size+1]; |
| 22 | + long long quotient=glob_n/comm_size, remainder=glob_n-comm_size*quotient; |
| 23 | + |
| 24 | + int i=0; col_partition[i]=0; i++; |
| 25 | + while(i<=remainder) { col_partition[i] = col_partition[i-1]+quotient+1; i++; } |
| 26 | + while(i<=comm_size) { col_partition[i] = col_partition[i-1]+quotient; i++; } |
98 | 27 |
|
99 |
| - bool eval_Jac_cons(const long long& n, const long long& m, |
100 |
| - const long long& num_cons, const long long* idx_cons, |
101 |
| - const double* x, bool new_x, double** Jac) |
102 |
| - { |
103 |
| - assert(n==n_vars); assert(m==n_cons); |
104 |
| - //no constraints |
105 |
| - return true; |
106 |
| - } |
| 28 | + _mass = new hiopVectorPar(glob_n, col_partition, comm); |
107 | 29 |
|
108 |
| - bool get_vecdistrib_info(long long global_n, long long* cols) |
109 |
| - { |
110 |
| - if(global_n==n_vars) |
111 |
| - for(int i=0; i<=comm_size; i++) cols[i]=col_partition[i]; |
112 |
| - else |
113 |
| - assert(false && "You shouldn't need distrib info for this size."); |
114 |
| - return true; |
115 |
| - } |
| 30 | + //if(my_rank==0) printf("reminder=%d quotient=%d\n", remainder, quotient); |
| 31 | + //printf("left=%d right=%d\n", col_partition[my_rank], col_partition[my_rank+1]); |
116 | 32 |
|
117 |
| - bool get_starting_point(const long long &global_n, double* x0) |
118 |
| - { |
119 |
| - assert(global_n==n_vars); |
120 |
| - long long n_local=col_partition[my_rank+1]-col_partition[my_rank]; |
121 |
| - for(int i=0; i<n_local; i++) |
122 |
| - x0[i]=0.0; |
123 |
| - return true; |
124 |
| - } |
125 |
| -private: |
126 |
| - int n_vars, n_cons; |
127 |
| - MPI_Comm comm; |
128 |
| - int my_rank, comm_size; |
129 |
| - long long* col_partition; |
130 |
| -public: |
131 |
| - inline int idx_local2global(long long global_n, int idx_local) |
132 |
| - { |
133 |
| - assert(idx_local + col_partition[my_rank]<col_partition[my_rank+1]); |
134 |
| - if(global_n==n_vars) |
135 |
| - return idx_local + col_partition[my_rank]; |
136 |
| - assert(false && "You shouldn't need global index for a vector of this size."); |
137 |
| - } |
138 |
| - inline int idx_global2local(long long global_n, long long idx_global) |
139 |
| - { |
140 |
| - assert(idx_global>=col_partition[my_rank] && "global index does not belong to this rank"); |
141 |
| - assert(idx_global< col_partition[my_rank+1] && "global index does not belong to this rank"); |
142 |
| - assert(global_n==n_vars && "your global_n does not match the number of variables?"); |
143 |
| - return idx_global-col_partition[my_rank]; |
| 33 | + //compute the mass |
| 34 | + double m1=2*_r / ((1+_r)*glob_n); |
| 35 | + double h =2*(1-_r) / (1+_r) / (glob_n-1) / glob_n; |
| 36 | + |
| 37 | + long long glob_n_start=col_partition[my_rank], glob_n_end=col_partition[my_rank+1]-1; |
| 38 | + |
| 39 | + double* mass = _mass->local_data(); //local slice |
| 40 | + double rescale = _b-_a; |
| 41 | + for(long long k=glob_n_start; k<=glob_n_end; k++) { |
| 42 | + mass[k-glob_n_start] = (m1 + (k-glob_n_start)*h) * rescale; |
| 43 | + //printf(" proc %d k=%d mass[k]=%g\n", my_rank, k, mass[k-glob_n_start]); |
144 | 44 | }
|
145 |
| -}; |
146 | 45 |
|
147 |
| -int main(int argc, char **argv) |
| 46 | + //_mass->print(stdout, NULL); |
| 47 | + //fflush(stdout); |
| 48 | +} |
| 49 | +Ex1Meshing1D::~Ex1Meshing1D() |
148 | 50 | {
|
149 |
| - int rank=0, numRanks=1; |
150 |
| -#ifdef WITH_MPI |
151 |
| - MPI_Init(&argc, &argv); |
152 |
| - assert(MPI_SUCCESS==MPI_Comm_rank(MPI_COMM_WORLD,&rank)); |
153 |
| - assert(MPI_SUCCESS==MPI_Comm_size(MPI_COMM_WORLD,&numRanks)); |
154 |
| - if(0==rank) printf("Support for MPI is enabled\n"); |
155 |
| -#endif |
| 51 | + delete _mass; |
| 52 | +} |
| 53 | + |
| 54 | +bool Ex1Meshing1D::get_vecdistrib_info(long long global_n, long long* cols) |
| 55 | +{ |
| 56 | + for(int i=0; i<=comm_size; i++) cols[i] = col_partition[i]; |
| 57 | +} |
| 58 | +void Ex1Meshing1D::applyM(DiscretizedFunction& f) |
| 59 | +{ |
| 60 | + f.componentMult(*this->_mass); |
| 61 | +} |
| 62 | + |
| 63 | +//converts the local indexes to global indexes |
| 64 | +long long Ex1Meshing1D::getGlobalIndex(long long i_local) const |
| 65 | +{ |
| 66 | + assert(0<=i_local); |
| 67 | + assert(i_local < col_partition[my_rank+1]-col_partition[my_rank]); |
| 68 | + |
| 69 | + return i_local+col_partition[my_rank]; |
| 70 | +} |
| 71 | + |
| 72 | +long long Ex1Meshing1D::getLocalIndex(long long i_global) const |
| 73 | +{ |
| 74 | + assert(i_global >= col_partition[my_rank]); |
| 75 | + assert(i_global < col_partition[my_rank+1]); |
| 76 | + return i_global-col_partition[my_rank]; |
| 77 | +} |
| 78 | + |
| 79 | +//for a function c(t), for given global index in the discretization |
| 80 | +// returns the corresponding continuous argument 't', which is in this |
| 81 | +// case the middle of the discretization interval. |
| 82 | +double Ex1Meshing1D::getFunctionArgument(long long i_global) const |
| 83 | +{ |
| 84 | + assert(i_global >= col_partition[my_rank]); |
| 85 | + assert(i_global < col_partition[my_rank+1]); |
| 86 | + |
| 87 | + const long & k = i_global; |
156 | 88 |
|
157 |
| - long long numVars=3; |
158 |
| - Ex1Interface problem(numVars); |
159 |
| - if(rank==0) printf("interface created\n"); |
160 |
| - hiop::hiopNlpDenseConstraints nlp(problem); |
161 |
| - if(rank==0) printf("nlp formulation created\n"); |
| 89 | + long long glob_n = size(); |
| 90 | + double m1=2*_r / ((1+_r)*glob_n); |
| 91 | + double h =2*(1-_r) / (1+_r) / (glob_n-1) / glob_n; |
| 92 | + |
| 93 | + //t is the middle of [k*m1 + k(k-1)/2*h, (k+1)m1+ (k+1)k/2*h] |
| 94 | + double t = 0.5*( (2*k+1)*m1 + k*k*h); |
| 95 | + return t; |
| 96 | +} |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | +/* DiscretizedFunction implementation */ |
| 101 | + |
| 102 | +DiscretizedFunction::DiscretizedFunction(Ex1Meshing1D* meshing) |
| 103 | + : hiopVectorPar(meshing->size(), meshing->get_col_partition(), meshing->get_comm()) |
| 104 | +{ |
| 105 | + _mesh = meshing; |
| 106 | +} |
| 107 | + |
| 108 | +// u'*v = u'*M*v, where u is 'this' |
| 109 | +double DiscretizedFunction::dotProductWith( const DiscretizedFunction& v_ ) const |
| 110 | +{ |
| 111 | + assert(v_._mesh->matches(this->_mesh)); |
| 112 | + double* M=_mesh->_mass->local_data(); |
| 113 | + double* u= this->data; |
| 114 | + double* v= v_.data; |
162 | 115 |
|
163 |
| - hiop::hiopAlgFilterIPM solver(&nlp); |
164 |
| - hiop::hiopSolveStatus status = solver.run(); |
165 |
| - double objective = solver.getObjective(); |
| 116 | + double dot=0.; |
| 117 | + for(int i=0; i<get_local_size(); i++) |
| 118 | + dot += u[i]*M[i]*v[i]; |
| 119 | + |
| 120 | + #ifdef WITH_MPI |
| 121 | + double dotprodG; |
| 122 | + int ierr = MPI_Allreduce(&dot, &dotprodG, 1, MPI_DOUBLE, MPI_SUM, comm); assert(MPI_SUCCESS==ierr); |
| 123 | + dot=dotprodG; |
| 124 | +#endif |
| 125 | + return dot; |
| 126 | +} |
| 127 | + |
| 128 | +// computes integral of 'this', that is sum (this[elem]*m[elem]) |
| 129 | +double DiscretizedFunction::integral() const |
| 130 | +{ |
| 131 | + //the base dotProductWith method would do it |
| 132 | + return hiopVectorPar::dotProductWith(*_mesh->_mass); |
| 133 | +} |
| 134 | + |
| 135 | +// norm(u) as sum(M[elem]*u[elem]^2) |
| 136 | +double DiscretizedFunction::twonorm() const |
| 137 | +{ |
| 138 | + double* M=_mesh->_mass->local_data(); |
| 139 | + double* u= this->data; |
| 140 | + |
| 141 | + double nrm_square=0.; |
| 142 | + for(int i=0; i<get_local_size(); i++) |
| 143 | + nrm_square += u[i]*u[i]*M[i]; |
166 | 144 |
|
167 |
| - printf("Objective: %18.12e\n", objective); |
168 | 145 | #ifdef WITH_MPI
|
169 |
| - MPI_Finalize(); |
170 |
| -#endif |
171 |
| - |
172 |
| - return 0; |
| 146 | + double nrm_squareG; |
| 147 | + int ierr = MPI_Allreduce(&nrm_square, &nrm_squareG, 1, MPI_DOUBLE, MPI_SUM, comm); assert(MPI_SUCCESS==ierr); |
| 148 | + nrm_square=nrm_squareG; |
| 149 | +#endif |
| 150 | + return sqrt(nrm_square); |
| 151 | +} |
| 152 | + |
| 153 | + |
| 154 | +//converts the local indexes to global indexes |
| 155 | +long long DiscretizedFunction::getGlobalIndex(long long i_local) const |
| 156 | +{ |
| 157 | + return _mesh->getGlobalIndex(i_local); |
| 158 | +} |
| 159 | + |
| 160 | +//for a function c(t), for given global index in the discretization |
| 161 | +// returns the corresponding continuous argument 't', which is in this |
| 162 | +// case the middle of the discretization interval. |
| 163 | +double DiscretizedFunction::getFunctionArgument(long long i_global) const |
| 164 | +{ |
| 165 | + return _mesh->getFunctionArgument(i_global); |
| 166 | +} |
| 167 | + |
| 168 | +//set the function value for a given global index |
| 169 | +void DiscretizedFunction::setFunctionValue(long long i_global, const double& value) |
| 170 | +{ |
| 171 | + long long i_local=_mesh->getLocalIndex(i_global); |
| 172 | + this->data[i_local]=value; |
| 173 | +} |
| 174 | + |
| 175 | + |
| 176 | + |
| 177 | +/* Ex1Interface class implementation */ |
| 178 | + |
| 179 | +/*set c to |
| 180 | + * c(t) = 1-10*t, for 0<=t<=1/10, |
| 181 | + * 0, for 1/10<=t<=1. |
| 182 | + */ |
| 183 | +void Ex1Interface::set_c() |
| 184 | +{ |
| 185 | + for(int i_local=0; i_local<n_local; i_local++) { |
| 186 | + //this will be based on 'my_rank', thus, different ranks get the appropriate global indexes |
| 187 | + long long n_global = c->getGlobalIndex(i_local); |
| 188 | + double t = c->getFunctionArgument(n_global); |
| 189 | + //if(t<=0.1) c->setFunctionValue(n_global, 1-10.*t); |
| 190 | + double cval; |
| 191 | + if(t<=0.1) cval = -1.+10.*t; |
| 192 | + else cval = 0.; |
| 193 | + |
| 194 | + c->setFunctionValue(n_global, cval); |
| 195 | + //printf("index %d t=%g value %g\n", n_global, t, cval); |
| 196 | + } |
173 | 197 | }
|
0 commit comments