Skip to content

Commit 9cc5a15

Browse files
committed
Example 1 - infinite dimensional
1 parent 9013ac3 commit 9cc5a15

File tree

7 files changed

+558
-156
lines changed

7 files changed

+558
-156
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ install(FILES src/Interface/hiopInterface.hpp
7878
##########################################################
7979
if (WITH_MAKETEST)
8080
enable_testing()
81+
add_test(NAME NlpDenseCons1_5H COMMAND $<TARGET_FILE:nlpDenseCons_ex1.exe> 500 1.0 -selfcheck)
82+
add_test(NAME NlpDenseCons1_5K COMMAND $<TARGET_FILE:nlpDenseCons_ex1.exe> 5000 1.0 -selfcheck)
8183
add_test(NAME NlpDenseCons2_5H COMMAND $<TARGET_FILE:nlpDenseCons_ex2.exe> 500 -selfcheck)
8284
add_test(NAME NlpDenseCons2_5K COMMAND $<TARGET_FILE:nlpDenseCons_ex2.exe> 5000 -selfcheck)
8385
add_test(NAME NlpDenseCons2_50K COMMAND $<TARGET_FILE:nlpDenseCons_ex2.exe> 50000 -selfcheck)

src/Drivers/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#add_executable(linalgTest.exe linalgTest.cpp)
22
#target_link_libraries(linalgTest.exe hiop ${LAPACK_LIBRARIES})
33

4-
add_executable(nlpDenseCons_ex1.exe nlpDenseCons_ex1.cpp)
4+
add_executable(nlpDenseCons_ex1.exe nlpDenseCons_ex1.cpp nlpDenseCons_ex1_driver.cpp)
55
target_link_libraries(nlpDenseCons_ex1.exe hiop ${LAPACK_LIBRARIES})
66

77
add_executable(nlpDenseCons_ex2.exe nlpDenseCons_ex2.cpp nlpDenseCons_ex2_driver.cpp)

src/Drivers/nlpDenseCons_ex1.cpp

Lines changed: 177 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,197 @@
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"
122

133
#include <cmath>
144
#include <cstdio>
155
#include <cassert>
166

17-
/* Example 1: min sum{x_i^2 | i=1,..,n} s.t. x_2>=1 */
7+
using namespace hiop;
188

19-
class Ex1Interface : public hiop::hiopInterfaceDenseConstraints
9+
Ex1Meshing1D::Ex1Meshing1D(double a, double b,
10+
long long glob_n, double r,
11+
MPI_Comm comm_)
2012
{
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;
7416
#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);
7819
#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++; }
9827

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);
10729

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]);
11632

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]);
14444
}
145-
};
14645

147-
int main(int argc, char **argv)
46+
//_mass->print(stdout, NULL);
47+
//fflush(stdout);
48+
}
49+
Ex1Meshing1D::~Ex1Meshing1D()
14850
{
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;
15688

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;
162115

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];
166144

167-
printf("Objective: %18.12e\n", objective);
168145
#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+
}
173197
}

0 commit comments

Comments
 (0)