Changeset 18942
- Timestamp:
- 12/04/14 15:43:24 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/cores/controlad_core.cpp
r18896 r18942 25 25 /*Cost function prototype*/ 26 26 void simulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs); 27 FemModel* presimulad(int* pintn, double** pX, FemModel* femmodel); 28 void postsimulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs); 27 29 /*}}}*/ 28 30 void controlad_core(FemModel* femmodel){ /*{{{*/ 29 31 30 32 /*Intermediaries*/ 33 FemModel* femmodelad=NULL; 31 34 int i; 32 35 long omode; … … 34 37 IssmDouble dxmind,gttold; 35 38 int maxsteps,maxiter; 36 int intn,numberofvertices,num_controls,solution_type; 37 IssmDouble *scaling_factors = NULL; 39 int intn,solution_type; 38 40 IssmPDouble *X = NULL; 39 41 IssmDouble *Xd = NULL; 40 IssmDouble *Gd = NULL;41 42 IssmPDouble *G = NULL; 42 bool onsid=true;43 43 44 44 /*Recover some parameters*/ 45 45 femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum); 46 femmodel->parameters->FindParam(&num_controls,InversionNumControlParametersEnum);47 46 femmodel->parameters->FindParam(&maxsteps,InversionMaxstepsEnum); 48 47 femmodel->parameters->FindParam(&maxiter,InversionMaxiterEnum); 49 48 femmodel->parameters->FindParam(&dxmind,InversionDxminEnum); dxmin=reCast<IssmPDouble>(dxmind); 50 49 femmodel->parameters->FindParam(>told,InversionGttolEnum); gttol=reCast<IssmPDouble>(gttold); 51 femmodel->parameters->FindParam(&scaling_factors,NULL,InversionControlScalingFactorsEnum);52 50 femmodel->parameters->SetParam(false,SaveResultsEnum); 53 numberofvertices=femmodel->vertices->NumberOfVertices();54 51 55 52 /*Initialize M1QN3 parameters*/ … … 71 68 long nsim = long(maxiter);/*Maximum number of function calls*/ 72 69 73 /*Get initial guess*/ 74 Vector<IssmDouble> *Xad = NULL; 75 GetVectorFromControlInputsx(&Xad,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"value",onsid); 76 Xd = Xad->ToMPISerial(); 77 Xad->GetSize(&intn); 78 X=xNew<IssmPDouble>(intn); 79 for(i=0;i<intn;i++) X[i]=reCast<IssmPDouble>(Xd[i]); 80 delete Xad; 81 _assert_(intn==numberofvertices*num_controls); 82 83 /*Get problem dimension and initialize gradient and initial guess*/ 70 /*Run the first part of simulad, in order to get things started!:*/ 71 femmodelad=presimulad(&intn,&X,femmodel); 72 73 /*Get problem dimension and initialize gradient: */ 84 74 long n = long(intn); 85 75 G = xNew<IssmPDouble>(n); 86 Gd = xNew<IssmDouble>(n);87 88 /*Scale control for M1QN3*/89 for(int i=0;i<numberofvertices;i++){90 for(int c=0;c<num_controls;c++){91 int index = num_controls*i+c;92 X[index] = X[index]/reCast<IssmPDouble>(scaling_factors[c]);93 }94 }95 76 96 77 /*Allocate m1qn3 working arrays (see doc)*/ … … 104 85 _printf0_("____________________________________________________________________\n"); 105 86 106 // first run before firingup the control optimization107 simulad(&indic,&n,X,&f,G,izs,rzs,(void*)femmodel);87 //run post simular phase, to fire up the control optimization 88 postsimulad(&indic,&n,X,&f,G,izs,rzs,(void*)femmodelad); 108 89 double f1=f; 109 90 … … 125 106 } 126 107 127 /*Constrain solution vector*/128 IssmDouble *XL = NULL;129 IssmDouble *XU = NULL;130 GetVectorFromControlInputsx(&XL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"lowerbound",onsid);131 GetVectorFromControlInputsx(&XU,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"upperbound",onsid);132 for(int i=0;i<numberofvertices;i++){133 for(int c=0;c<num_controls;c++){134 int index = num_controls*i+c;135 X[index] = X[index]*reCast<IssmPDouble>(scaling_factors[c]);136 if(X[index]>XU[index]) X[index]=reCast<IssmPDouble>(XU[index]);137 if(X[index]<XL[index]) X[index]=reCast<IssmPDouble>(XL[index]);138 }139 }140 141 108 /*Save results:*/ 142 109 femmodel->results->AddObject(new GenericExternalResult<IssmPDouble*>(femmodel->results->Size()+1,AutodiffJacobianEnum,G,n,1,1,0.0)); … … 147 114 xDelete<double>(X); 148 115 xDelete<double>(dz); 149 xDelete<IssmDouble>(scaling_factors);150 116 }/*}}}*/ 151 void simulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs){ /*{{{*/117 FemModel* presimulad(int* pintn, double** pX, FemModel* femmodel){ /*{{{*/ 152 118 153 119 /*Intermediaries:*/ … … 157 123 char* toolkitsfilename=NULL; 158 124 char* lockfilename=NULL; 159 IssmPDouble* G2=NULL;160 bool onsid=true;161 IssmDouble *XL = NULL;162 IssmDouble *XU = NULL;163 125 int solution_type; 164 FemModel *femmodel = NULL;165 FemModel *femmodelad = NULL;166 126 IssmDouble pfd; 127 IssmDouble* Xd=NULL; 128 int intn; 129 IssmPDouble* X=NULL; 167 130 int i; 168 131 169 /*Recover Femmodel*/170 femmodel = (FemModel*)dzs;171 172 /*Recover number of cost functions responses*/173 int num_responses,num_controls,numberofvertices;174 IssmDouble* scaling_factors = NULL;175 femmodel->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum);176 femmodel->parameters->FindParam(&num_controls,InversionNumControlParametersEnum);177 femmodel->parameters->FindParam(&scaling_factors,NULL,InversionControlScalingFactorsEnum);178 numberofvertices=femmodel->vertices->NumberOfVertices();179 180 /*Constrain input vector*/181 GetVectorFromControlInputsx(&XL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"lowerbound",onsid);182 GetVectorFromControlInputsx(&XU,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"upperbound",onsid);183 for(int i=0;i<numberofvertices;i++){184 for(int c=0;c<num_controls;c++){185 int index = num_controls*i+c;186 X[index] = X[index]*reCast<IssmPDouble>(scaling_factors[c]);187 if(X[index]>reCast<IssmPDouble>(XU[index])) X[index]=reCast<IssmPDouble>(XU[index]);188 if(X[index]<reCast<IssmPDouble>(XL[index])) X[index]=reCast<IssmPDouble>(XL[index]);189 }190 }191 192 132 /*Now things get complicated. The femmodel we recovered did not initialize an AD trace, so we can't compute gradients with it. We are going to recreate 193 133 *a new femmodel, identical in all aspects to the first one, with trace on though, which will allow us to run the forward mode and get the gradient … … 199 139 femmodel->parameters->FindParam(&lockfilename,LockFileNameEnum); 200 140 201 femmodelad=new FemModel(rootpath, inputfilename, outputfilename, toolkitsfilename, lockfilename, femmodel->comm, femmodel->solution_type,X); 202 femmodel=femmodelad; //We can do this, because femmodel is being called from outside, not by reference, so we won't erase it 203 141 femmodel=new FemModel(rootpath, inputfilename, outputfilename, toolkitsfilename, lockfilename, femmodel->comm, femmodel->solution_type,NULL); 142 143 144 /*Get initial guess:*/ 145 femmodel->parameters->FindParam(&Xd,&intn,AutodiffXpEnum); 146 X=xNew<IssmPDouble>(intn); for(i=0;i<intn;i++) X[i]=reCast<IssmPDouble>(Xd[i]); 147 148 xDelete<char>(rootpath); 149 xDelete<char>(inputfilename); 150 xDelete<char>(outputfilename); 151 xDelete<char>(toolkitsfilename); 152 xDelete<char>(lockfilename); 153 xDelete<IssmDouble>(Xd); 154 155 *pintn=intn; 156 *pX=X; 157 158 return femmodel; 159 160 } /*}}}*/ 161 void postsimulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs){ /*{{{*/ 162 163 /*Intermediaries:*/ 164 char* rootpath=NULL; 165 char* inputfilename=NULL; 166 char* outputfilename=NULL; 167 char* toolkitsfilename=NULL; 168 char* lockfilename=NULL; 169 IssmPDouble* G2=NULL; 170 int solution_type; 171 FemModel *femmodel = NULL; 172 IssmDouble pfd; 173 int i; 174 175 /*Recover Femmodel*/ 176 femmodel = (FemModel*)dzs; 177 178 /*Recover number of cost functions responses*/ 179 int num_responses; 180 femmodel->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum); 181 204 182 /*Recover some parameters*/ 205 183 femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum); … … 236 214 /*Constrain X and G*/ 237 215 IssmDouble Gnorm = 0.; 238 for(int i=0;i<numberofvertices;i++){ 239 for(int c=0;c<num_controls;c++){ 240 int index = num_controls*i+c; 241 if(X[index]>=XU[index]) G[index]=0.; 242 if(X[index]<=XL[index]) G[index]=0.; 243 G[index] = G[index]*reCast<IssmPDouble>(scaling_factors[c]); 244 X[index] = X[index]/reCast<IssmPDouble>(scaling_factors[c]); 245 Gnorm += G[index]*G[index]; 246 } 247 } 216 for(long i=0;i<*n;i++) Gnorm += G[i]*G[i]; 248 217 Gnorm = sqrt(Gnorm); 249 218 … … 255 224 /*Clean-up and return*/ 256 225 xDelete<IssmDouble>(Jlist); 257 xDelete<IssmDouble>(XU);258 xDelete<IssmDouble>(XL);259 226 xDelete<IssmPDouble>(G2); 260 xDelete<IssmDouble>(scaling_factors); 227 228 xDelete<char>(rootpath); 229 xDelete<char>(inputfilename); 230 xDelete<char>(outputfilename); 231 xDelete<char>(toolkitsfilename); 232 xDelete<char>(lockfilename); 233 234 } /*}}}*/ 235 void simulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs){ /*{{{*/ 236 237 /*Intermediaries:*/ 238 char* rootpath=NULL; 239 char* inputfilename=NULL; 240 char* outputfilename=NULL; 241 char* toolkitsfilename=NULL; 242 char* lockfilename=NULL; 243 IssmPDouble* G2=NULL; 244 int solution_type; 245 FemModel *femmodel = NULL; 246 FemModel *femmodelad = NULL; 247 IssmDouble pfd; 248 int i; 249 250 /*Recover Femmodel*/ 251 femmodel = (FemModel*)dzs; 252 253 /*Recover number of cost functions responses*/ 254 int num_responses; 255 femmodel->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum); 256 257 /*Now things get complicated. The femmodel we recovered did not initialize an AD trace, so we can't compute gradients with it. We are going to recreate 258 *a new femmodel, identical in all aspects to the first one, with trace on though, which will allow us to run the forward mode and get the gradient 259 in one run of the solution core. So first recover the filenames required for the FemModel constructor, then call a new ad tailored constructor:*/ 260 femmodel->parameters->FindParam(&rootpath,RootPathEnum); 261 femmodel->parameters->FindParam(&inputfilename,InputFileNameEnum); 262 femmodel->parameters->FindParam(&outputfilename,OutputFileNameEnum); 263 femmodel->parameters->FindParam(&toolkitsfilename,ToolkitsFileNameEnum); 264 femmodel->parameters->FindParam(&lockfilename,LockFileNameEnum); 265 266 femmodelad=new FemModel(rootpath, inputfilename, outputfilename, toolkitsfilename, lockfilename, femmodel->comm, femmodel->solution_type,X); 267 femmodel=femmodelad; //We can do this, because femmodel is being called from outside, not by reference, so we won't erase it 268 269 /*Recover some parameters*/ 270 femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum); 271 272 /*Compute solution:*/ 273 void (*solutioncore)(FemModel*)=NULL; 274 CorePointerFromSolutionEnum(&solutioncore,femmodel->parameters,solution_type); 275 solutioncore(femmodel); 276 277 /*Compute objective function*/ 278 IssmDouble* Jlist = NULL; 279 femmodel->CostFunctionx(&pfd,&Jlist,NULL); *pf=reCast<IssmPDouble>(pfd); 280 _printf0_("f(x) = "<<setw(12)<<setprecision(7)<<*pf<<" | "); 281 282 /*Compute gradient using AD. Gradient is in the results after the ad_core is called*/ 283 adgradient_core(femmodel); 284 285 if(IssmComm::GetRank()==0){ 286 IssmPDouble* G_temp=NULL; 287 GenericExternalResult<IssmPDouble*>* gradient=(GenericExternalResult<IssmPDouble*>*)femmodel->results->FindResult(AutodiffJacobianEnum); _assert_(gradient); 288 G_temp=gradient->GetValues(); 289 /*copy onto G2, to avoid a leak: */ 290 G2=xNew<IssmPDouble>(*n); 291 xMemCpy<IssmPDouble>(G2,G_temp,*n); 292 } 293 else G2=xNew<IssmPDouble>(*n); 294 295 /*MPI broadcast results:*/ 296 ISSM_MPI_Bcast(G2,*n,ISSM_MPI_PDOUBLE,0,IssmComm::GetComm()); 297 298 /*Send gradient to m1qn3 core: */ 299 for(long i=0;i<*n;i++) G[i] = G2[i]; 300 301 /*Recover Gnorm: */ 302 IssmDouble Gnorm = 0.; 303 for(int i=0;i<*n;i++) Gnorm += G[i]*G[i]; 304 Gnorm = sqrt(Gnorm); 305 306 /*Print info*/ 307 _printf0_(" "<<setw(12)<<setprecision(7)<<Gnorm<<" |"); 308 for(int i=0;i<num_responses;i++) _printf0_(" "<<setw(12)<<setprecision(7)<<Jlist[i]); 309 _printf0_("\n"); 310 311 /*Clean-up and return*/ 312 xDelete<IssmDouble>(Jlist); 313 xDelete<IssmPDouble>(G2); 261 314 262 315 xDelete<char>(rootpath);
Note:
See TracChangeset
for help on using the changeset viewer.