Changeset 18942


Ignore:
Timestamp:
12/04/14 15:43:24 (10 years ago)
Author:
Eric.Larour
Message:

CHG: rehooking ad gradient core

File:
1 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/c/cores/controlad_core.cpp

    r18896 r18942  
    2525/*Cost function prototype*/
    2626void simulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs);
     27FemModel* presimulad(int* pintn, double** pX, FemModel* femmodel);
     28void postsimulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs);
    2729/*}}}*/
    2830void controlad_core(FemModel* femmodel){ /*{{{*/
    2931
    3032        /*Intermediaries*/
     33        FemModel*    femmodelad=NULL;
    3134        int          i;
    3235        long         omode;
     
    3437        IssmDouble   dxmind,gttold;
    3538        int          maxsteps,maxiter;
    36         int          intn,numberofvertices,num_controls,solution_type;
    37         IssmDouble  *scaling_factors = NULL;
     39        int          intn,solution_type;
    3840        IssmPDouble  *X  = NULL;
    3941        IssmDouble   *Xd  = NULL;
    40         IssmDouble   *Gd  = NULL;
    4142        IssmPDouble  *G  = NULL;
    42         bool onsid=true;
    4343
    4444        /*Recover some parameters*/
    4545        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    46         femmodel->parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
    4746        femmodel->parameters->FindParam(&maxsteps,InversionMaxstepsEnum);
    4847        femmodel->parameters->FindParam(&maxiter,InversionMaxiterEnum);
    4948        femmodel->parameters->FindParam(&dxmind,InversionDxminEnum); dxmin=reCast<IssmPDouble>(dxmind);
    5049        femmodel->parameters->FindParam(&gttold,InversionGttolEnum); gttol=reCast<IssmPDouble>(gttold);
    51         femmodel->parameters->FindParam(&scaling_factors,NULL,InversionControlScalingFactorsEnum);
    5250        femmodel->parameters->SetParam(false,SaveResultsEnum);
    53         numberofvertices=femmodel->vertices->NumberOfVertices();
    5451
    5552        /*Initialize M1QN3 parameters*/
     
    7168        long nsim  = long(maxiter);/*Maximum number of function calls*/
    7269
    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: */
    8474        long n = long(intn);
    8575        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         }
    9576
    9677        /*Allocate m1qn3 working arrays (see doc)*/
     
    10485        _printf0_("____________________________________________________________________\n");
    10586
    106         //first run before firing up the control optimization
    107         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);
    10889        double f1=f;
    10990
     
    125106        }
    126107       
    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 
    141108        /*Save results:*/
    142109        femmodel->results->AddObject(new GenericExternalResult<IssmPDouble*>(femmodel->results->Size()+1,AutodiffJacobianEnum,G,n,1,1,0.0));
     
    147114        xDelete<double>(X);
    148115        xDelete<double>(dz);
    149         xDelete<IssmDouble>(scaling_factors);
    150116}/*}}}*/
    151 void simulad(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs){ /*{{{*/
     117FemModel* presimulad(int* pintn, double** pX, FemModel* femmodel){ /*{{{*/
    152118
    153119        /*Intermediaries:*/
     
    157123        char* toolkitsfilename=NULL;
    158124        char* lockfilename=NULL;
    159         IssmPDouble* G2=NULL;
    160         bool onsid=true;
    161         IssmDouble  *XL = NULL;
    162         IssmDouble  *XU = NULL;
    163125        int         solution_type;
    164         FemModel   *femmodel  =  NULL;
    165         FemModel   *femmodelad  = NULL;
    166126        IssmDouble    pfd;
     127        IssmDouble*   Xd=NULL;
     128        int           intn;
     129        IssmPDouble*   X=NULL;
    167130        int            i;
    168131       
    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 
    192132        /*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
    193133         *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
     
    199139        femmodel->parameters->FindParam(&lockfilename,LockFileNameEnum);
    200140
    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} /*}}}*/
     161void 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
    204182        /*Recover some parameters*/
    205183        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
     
    236214        /*Constrain X and G*/
    237215        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];
    248217        Gnorm = sqrt(Gnorm);
    249218
     
    255224        /*Clean-up and return*/
    256225        xDelete<IssmDouble>(Jlist);
    257         xDelete<IssmDouble>(XU);
    258         xDelete<IssmDouble>(XL);
    259226        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} /*}}}*/
     235void 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);
    261314       
    262315        xDelete<char>(rootpath);
Note: See TracChangeset for help on using the changeset viewer.