Ice Sheet System Model  4.18
Code documentation
Functions
ad_core.cpp File Reference
#include <set>
#include "./cores.h"
#include "../toolkits/toolkits.h"
#include "../classes/classes.h"
#include "../shared/shared.h"
#include "../modules/modules.h"
#include "../solutionsequences/solutionsequences.h"

Go to the source code of this file.

Functions

void ad_core (FemModel *femmodel)
 

Function Documentation

◆ ad_core()

void ad_core ( FemModel femmodel)

Definition at line 24 of file ad_core.cpp.

24  {
25 
26  /*diverse: */
27  int i;
28  int dummy;
29  int num_dependents=0;
30  int num_independents=0;
31  bool isautodiff,iscontrol;
32  char *driver = NULL;
33  size_t tape_stats[15];
34 
35  /*state variables: */
36  IssmDouble *axp = NULL;
37  double *xp = NULL;
38  int my_rank=IssmComm::GetRank();
39 
40  /*AD mode on?: */
43 
44  if(isautodiff && !iscontrol){
45 
46  #if defined(_HAVE_ADOLC_)
47  if(VerboseAutodiff())_printf0_(" start ad core\n");
48 
49  /*First, stop tracing: */
50  trace_off();
51 
52  /*Print tape statistics so that user can kill this run if something is off already:*/
53  if(VerboseAutodiff()){ /*{{{*/
54  tapestats(my_rank,tape_stats); //reading of tape statistics
55  int commSize=IssmComm::GetSize();
56  int *sstats=new int[7];
57  sstats[0]=tape_stats[NUM_OPERATIONS];
58  sstats[1]=tape_stats[OP_FILE_ACCESS];
59  sstats[2]=tape_stats[NUM_LOCATIONS];
60  sstats[3]=tape_stats[LOC_FILE_ACCESS];
61  sstats[4]=tape_stats[NUM_VALUES];
62  sstats[5]=tape_stats[VAL_FILE_ACCESS];
63  sstats[6]=tape_stats[TAY_STACK_SIZE];
64  int *rstats=NULL;
65  if (my_rank==0) rstats=new int[commSize*7];
67  if (my_rank==0) {
68  int offset=50;
69  int rOffset=(commSize/10)+1;
70  _printf_(" ADOLC statistics: \n");
71  _printf_(" "<<setw(offset)<<left<<"#independents: " <<setw(12)<<right<<tape_stats[NUM_INDEPENDENTS] << "\n");
72  _printf_(" "<<setw(offset)<<left<<"#dependents: " <<setw(12)<<right<<tape_stats[NUM_DEPENDENTS] << "\n");
73  _printf_(" "<<setw(offset)<<left<<"max #live active variables: " <<setw(12)<<right<<tape_stats[NUM_MAX_LIVES] << "\n");
74  _printf_(" operations: entry size "<< sizeof(unsigned char) << " Bytes \n");
75  _printf_(" "<<setw(offset)<<left<<" #entries in buffer (AutodiffObufsizeEnum) " <<setw(12)<<right<<tape_stats[OP_BUFFER_SIZE] << "\n");
76  for (int r=0;r<commSize;++r)
77  _printf_(" ["<<setw(rOffset)<<right<<r<<"]"<<setw(offset-rOffset-4)<<left<<" #entries total" <<setw(12)<<right<<rstats[r*7+0] << (rstats[r*7+1]?" ->file":"") << "\n");
78  _printf_(" locations: entry size " << sizeof(locint) << " Bytes\n");
79  _printf_(" "<<setw(offset)<<left<<" #entries in buffer (AutodiffLbufsizeEnum) " <<setw(12)<<right<<tape_stats[LOC_BUFFER_SIZE] << "\n");
80  for (int r=0;r<commSize;++r)
81  _printf_(" ["<<setw(rOffset)<<right<<r<<"]"<<setw(offset-rOffset-4)<<left<<" #entries total" <<setw(12)<<right<<rstats[r*7+2] << (rstats[r*7+3]?" ->file":"") << "\n");
82  _printf_(" constant values: entry size " << sizeof(double) << " Bytes\n");
83  _printf_(" "<<setw(offset)<<left<<" #entries in buffer (AutodiffCbufsizeEnum) " <<setw(12)<<right<<tape_stats[VAL_BUFFER_SIZE] << "\n");
84  for (int r=0;r<commSize;++r)
85  _printf_(" ["<<setw(rOffset)<<right<<r<<"]"<<setw(offset-rOffset-4)<<left<<" #entries total" <<setw(12)<<right<<rstats[r*7+4] << (rstats[r*7+5]?" ->file":"") << "\n");
86  _printf_(" Taylor stack: entry size " << sizeof(revreal) << " Bytes\n");
87  _printf_(" "<<setw(offset)<<left<<" #entries in buffer (AutodiffTbufsizeEnum) " <<setw(12)<<right<<tape_stats[TAY_BUFFER_SIZE] << "\n");
88  for (int r=0;r<commSize;++r)
89  _printf_(" ["<<setw(rOffset)<<right<<r<<"]"<<setw(offset-rOffset-4)<<left<<" #entries total" <<setw(12)<<right<<rstats[r*7+6] << (rstats[r*7+6]>tape_stats[TAY_BUFFER_SIZE]?" ->file":"") << "\n");
90  delete []rstats;
91  }
92  delete [] sstats;
93  } /*}}}*/
94 
95  /*retrieve parameters: */
98 
99  /*if no dependents, no point in running a driver: */
100  if(!(num_dependents*num_independents)) return;
101 
102  /*for adolc to run in parallel, we 0 out on rank~=0:*/
103  if (my_rank!=0){
104  num_dependents=0; num_independents=0;
105  }
106 
107  /*retrieve state variable: */
109 
110  /* driver argument */
111  xp=xNew<double>(num_independents);
112  for(i=0;i<num_independents;i++){
113  xp[i]=reCast<double,IssmDouble>(axp[i]);
114  }
115 
116  /*get the EDF pointer:*/
117  ext_diff_fct *anEDF_for_solverx_p=xDynamicCast<GenericParam<Adolc_edf> * >(femmodel->parameters->FindParamObject(AdolcParamEnum))->GetParameterValue().myEDF_for_solverx_p;
118 
119  /*Branch according to AD driver: */
121 
122  if (strcmp(driver,"fos_forward")==0){ /*{{{*/
123 
124  int anIndepIndex;
125  double *tangentDir = NULL;
126  double *jacTimesTangentDir = NULL;
127  double *theOutput = NULL;
128 
129  /*retrieve direction index: */
131 
132  if (anIndepIndex<0 || anIndepIndex>=num_independents) _error_("index value for AutodiffFosForwardIndexEnum should be in [0,num_independents-1]");
133 
134  tangentDir=xNewZeroInit<double>(num_independents);
135  tangentDir[anIndepIndex]=1.0;
136 
137  jacTimesTangentDir=xNew<double>(num_dependents);
138  theOutput=xNew<double>(num_dependents);
139 
140  /*set the forward method function pointer: */
141 #ifdef _HAVE_GSL_
142  anEDF_for_solverx_p->fos_forward=EDF_fos_forward_for_solverx;
143 #endif
144 
145  /*call driver: */
146  fos_forward(my_rank,num_dependents,num_independents, 0, xp, tangentDir, theOutput, jacTimesTangentDir );
147 
148  /*add to results*/
149  femmodel->results->AddObject(new GenericExternalResult<IssmPDouble*>(femmodel->results->Size()+1,AutodiffJacobianEnum,jacTimesTangentDir,num_dependents,1,0,0.0));
150 
151  /*free resources :*/
152  xDelete(theOutput);
153  xDelete(jacTimesTangentDir);
154  xDelete(tangentDir);
155  } /*}}}*/
156  else if ((strcmp(driver,"fov_forward")==0) || (strcmp(driver,"fov_forward_all")==0)){ /*{{{*/
157 
158  int tangentDirNum;
159  int dummy;
160  int *indepIndices = NULL;
161  double **jacTimesSeed = NULL;
162  double **seed = NULL;
163  double *theOutput = NULL;
164  std::set<unsigned int> anIndexSet;
165 
166  /*retrieve directions:*/
167  if (strcmp(driver,"fov_forward_all")==0){
168  tangentDirNum=num_independents;
169  indepIndices=xNewZeroInit<int>(tangentDirNum);
170  for(i=0;i<num_independents;i++)indepIndices[i]=1;
171  }
172  else{
173  femmodel->parameters->FindParam(&indepIndices,&tangentDirNum,&dummy,AutodiffFovForwardIndicesEnum);
174  }
175 
176  /*Some checks: */
177  if (tangentDirNum<1 || tangentDirNum>num_independents) _error_("tangentDirNum should be in [1,num_independents]");
178 
179  /* full Jacobian or Jacobian projection:*/
180  jacTimesSeed=xNew<double>(num_dependents,tangentDirNum);
181 
182  /*set the forward method function pointers: */
183 #ifdef _HAVE_GSL_
184  anEDF_for_solverx_p->fov_forward=EDF_fov_forward_for_solverx;
185 #endif
186  // anEDF_for_solverx_p->fov_reverse=EDF_fov_reverse_for_solverx;
187 
188  /*seed matrix: */
189  seed=xNewZeroInit<double>(num_independents,tangentDirNum);
190 
191  /*collect indices in a set to prevent accidental duplicates as long as we don't do compression:*/
192  for (int i=0; i<tangentDirNum; ++i) {
193  /* make sure the index is in range*/
194  if (indepIndices[i]>num_independents) {
195  _error_("indepIndices values must be in [0,num_independents-1]");
196  }
197  if (anIndexSet.find(indepIndices[i])!=anIndexSet.end()) {
198  _error_("duplicate indepIndices values are not allowed until we implement Jacobian decompression");
199  }
200  anIndexSet.insert(indepIndices[i]);
201  /* now populate the seed matrix from the set of independent indices;
202  * simple setup with a single 1.0 per column and at most a single 1.0 per row*/
203  seed[indepIndices[i]][i]=1.0;
204  }
205 
206  /*allocate output: */
207  theOutput=xNew<double>(num_dependents);
208 
209  /*call driver: */
210  fov_forward(my_rank,num_dependents,num_independents, tangentDirNum, xp, seed, theOutput, jacTimesSeed );
211  /*Free resources: */
212  xDelete(theOutput);
213  xDelete(indepIndices);
214  xDelete(seed);
215 
216  /*add to results: */
217  femmodel->results->AddObject(new GenericExternalResult<IssmPDouble*>(femmodel->results->Size()+1,AutodiffJacobianEnum,*jacTimesSeed,num_dependents*tangentDirNum,1,0,0.0));
218 
219  /*Free resources: */
220  xDelete(jacTimesSeed);
221  xDelete(indepIndices);
222  } /*}}}*/
223  else if (strcmp(driver,"fos_reverse")==0) { /*{{{*/
224 
225  int aDepIndex=0;
226  double *aWeightVector=NULL;
227  double *weightVectorTimesJac=NULL;
228 
229  /*retrieve direction index: */
231  aWeightVector=xNewZeroInit<double>(num_dependents);
232  if (my_rank==0) {
233  if (aDepIndex<0 || aDepIndex>=num_dependents) _error_("index value for AutodiffFosReverseIndexEnum should be in [0,num_dependents-1]");
234  aWeightVector[aDepIndex]=1.0;
235  }
236  weightVectorTimesJac=xNew<double>(num_independents);
237 
238  /*set the forward method function pointer: */
239 #ifdef _HAVE_GSL_
240  anEDF_for_solverx_p->fos_reverse=EDF_fos_reverse_for_solverx;
241 #endif
242 #ifdef _HAVE_MUMPS_
243  anEDF_for_solverx_p->fos_reverse_iArr=fos_reverse_mumpsSolveEDF;
244 #endif
245 
246  /*call driver: */
247  fos_reverse(my_rank,num_dependents,num_independents, aWeightVector, weightVectorTimesJac );
248 
249  /*add to results*/
250  femmodel->results->AddObject(new GenericExternalResult<IssmPDouble*>(femmodel->results->Size()+1,AutodiffJacobianEnum,weightVectorTimesJac,num_independents,1,0,0.0));
251 
252  /*free resources :*/
253  xDelete(weightVectorTimesJac);
254  xDelete(aWeightVector);
255  } /*}}}*/
256  else if ((strcmp(driver,"fov_reverse")==0) || (strcmp(driver,"fov_reverse_all")==0)){ /*{{{*/
257 
258  int* depIndices=NULL;
259  int weightNum;
260  int dummy;
261  double **weightsTimesJac=NULL;
262  double **weights=NULL;
263  std::set<unsigned int> anIndexSet;
264 
265  /*retrieve directions:*/
266  if (strcmp(driver,"fov_reverse_all")==0){
267  weightNum=num_dependents;
268  depIndices=xNewZeroInit<int>(weightNum);
269  for(i=0;i<num_dependents;i++)depIndices[i]=1;
270  }
271  else{
272  femmodel->parameters->FindParam(&depIndices,&weightNum,&dummy,AutodiffFovForwardIndicesEnum);
273  }
274 
275  /*Some checks: */
276  if (weightNum<1 || weightNum>num_dependents) _error_("tangentDirNum should be in [1,num_dependents]");
277 
278  /* full Jacobian or Jacobian projection:*/
279  weightsTimesJac=xNew<double>(weightNum,num_independents);
280 
281  /*set the forward method function pointers: */
282  #ifdef _HAVE_GSL_
283  anEDF_for_solverx_p->fov_reverse=EDF_fov_reverse_for_solverx;
284  #endif
285 
286  /*seed matrix: */
287  weights=xNewZeroInit<double>(weightNum,num_dependents);
288 
289  /*collect indices in a set to prevent accidental duplicates as long as we don't do compression:*/
290  for (int i=0; i<weightNum; ++i) {
291  /* make sure the index is in range*/
292  if (depIndices[i]>num_dependents) {
293  _error_("depIndices values must be in [0,num_dependents-1]");
294  }
295  if (anIndexSet.find(depIndices[i])!=anIndexSet.end()) {
296  _error_("duplicate depIndices values are not allowed until we implement Jacobian decompression");
297  }
298  anIndexSet.insert(depIndices[i]);
299  /* now populate the seed matrix from the set of independent indices;
300  * simple setup with a single 1.0 per column and at most a single 1.0 per row*/
301  weights[depIndices[i]][i]=1.0;
302  }
303 
304  /*call driver: */
305  fov_reverse(my_rank,num_dependents,num_independents, weightNum, weights, weightsTimesJac );
306 
307  /*add to results: */
308  femmodel->results->AddObject(new GenericExternalResult<IssmPDouble*>(femmodel->results->Size()+1,AutodiffJacobianEnum,*weightsTimesJac,weightNum*num_independents,1,0,0.0));
309 
310  /*Free resources: */
311  xDelete(weights);
312  xDelete(weightsTimesJac);
313  xDelete(depIndices);
314  } /*}}}*/
315  else _error_("driver: " << driver << " not yet supported!");
316 
317  if(VerboseAutodiff())_printf0_(" end AD core\n");
318 
319  /*Free resources: */
320  xDelete(xp);
321  xDelete(axp);
322  xDelete(driver);
323 
324  #elif defined(_HAVE_CODIPACK_)
325  if(VerboseAutodiff())_printf0_(" start CoDiPack ad core\n");
326 
327  /*First, stop tracing: */
328  auto& tape_codi = IssmDouble::getGlobalTape();
329  tape_codi.setPassive();
330 
331  if(VerboseAutodiff()){ /*{{{*/
332  if(my_rank == 0) {
333  // FIXME codi "just because" for now
334  tape_codi.printStatistics(std::cout);
335  codi_global.print(std::cout);
336  }
337  }
338 
339  /*retrieve parameters: */
342 
343  /*if no dependents, no point in running a driver: */
344  if(!(num_dependents*num_independents)) return;
345 
346  /*Branch according to AD driver: */
348  if(VerboseAutodiff())_printf0_(" driver: " << driver << "\n");
349 
350  if (strcmp(driver,"fos_reverse")==0) { /*{{{*/
351  if(VerboseAutodiff())_printf0_(" CoDiPack fos_reverse\n");
352  int aDepIndex=0;
353  double *weightVectorTimesJac=NULL;
354 
355  /*retrieve direction index: */
357  if (my_rank==0) {
358  if (aDepIndex<0 || aDepIndex>=num_dependents
359  || codi_global.output_indices.size() <= aDepIndex){
360  _error_("index value for AutodiffFosReverseIndexEnum should be in [0,num_dependents-1]");
361  }
362  tape_codi.setGradient(codi_global.output_indices[aDepIndex], 1.0);
363  }
364 
365  tape_codi.evaluate();
366 
367  weightVectorTimesJac=xNew<double>(num_independents);
368  /*call driver: */
369  auto in_size = codi_global.input_indices.size();
370  for(size_t i = 0; i < in_size; ++i) {
371  weightVectorTimesJac[i] = tape_codi.getGradient(codi_global.input_indices[i]);
372  }
373 
374  /*add to results*/
375  femmodel->results->AddObject(new GenericExternalResult<IssmPDouble*>(femmodel->results->Size()+1,AutodiffJacobianEnum,weightVectorTimesJac,num_independents,1,0,0.0));
376 
377  /*free resources :*/
378  xDelete(weightVectorTimesJac);
379  } /*}}}*/
380  else _error_("driver: " << driver << " not yet supported!");
381 
382  if(VerboseAutodiff())_printf0_(" end CoDiPack ad core\n");
383  xDelete(driver);
384  #else
385  _error_("Should not be requesting AD drivers when an AD library is not available!");
386  #endif
387  }
388 }
DataSet::Size
int Size()
Definition: DataSet.cpp:399
IssmDouble
double IssmDouble
Definition: types.h:37
_printf0_
#define _printf0_(StreamArgs)
Definition: Print.h:29
DataSet::AddObject
int AddObject(Object *object)
Definition: DataSet.cpp:252
_printf_
#define _printf_(StreamArgs)
Definition: Print.h:22
AutodiffXpEnum
@ AutodiffXpEnum
Definition: EnumDefinitions.h:57
FemModel::parameters
Parameters * parameters
Definition: FemModel.h:46
IssmComm::GetComm
static ISSM_MPI_Comm GetComm(void)
Definition: IssmComm.cpp:30
AutodiffFosForwardIndexEnum
@ AutodiffFosForwardIndexEnum
Definition: EnumDefinitions.h:45
InversionIscontrolEnum
@ InversionIscontrolEnum
Definition: EnumDefinitions.h:218
FemModel::results
Results * results
Definition: FemModel.h:48
AutodiffDriverEnum
@ AutodiffDriverEnum
Definition: EnumDefinitions.h:44
AutodiffFovForwardIndicesEnum
@ AutodiffFovForwardIndicesEnum
Definition: EnumDefinitions.h:47
AutodiffJacobianEnum
@ AutodiffJacobianEnum
Definition: EnumDefinitions.h:978
ISSM_MPI_INT
#define ISSM_MPI_INT
Definition: issmmpi.h:127
VerboseAutodiff
bool VerboseAutodiff(void)
Definition: Verbosity.cpp:29
xDelete
void xDelete(T **&aT_pp)
Definition: MemOps.h:97
IssmComm::GetSize
static int GetSize(void)
Definition: IssmComm.cpp:46
AutodiffFosReverseIndexEnum
@ AutodiffFosReverseIndexEnum
Definition: EnumDefinitions.h:46
AutodiffIsautodiffEnum
@ AutodiffIsautodiffEnum
Definition: EnumDefinitions.h:50
GenericExternalResult
Definition: GenericExternalResult.h:21
IssmComm::GetRank
static int GetRank(void)
Definition: IssmComm.cpp:34
_error_
#define _error_(StreamArgs)
Definition: exceptions.h:49
AdolcParamEnum
@ AdolcParamEnum
Definition: EnumDefinitions.h:12
AutodiffNumDependentsEnum
@ AutodiffNumDependentsEnum
Definition: EnumDefinitions.h:52
Parameters::FindParam
void FindParam(bool *pinteger, int enum_type)
Definition: Parameters.cpp:262
Parameters::FindParamObject
Param * FindParamObject(int enum_type)
Definition: Parameters.cpp:588
AutodiffNumIndependentsEnum
@ AutodiffNumIndependentsEnum
Definition: EnumDefinitions.h:53
ISSM_MPI_Gather
int ISSM_MPI_Gather(void *sendbuf, int sendcnt, ISSM_MPI_Datatype sendtype, void *recvbuf, int recvcnt, ISSM_MPI_Datatype recvtype, int root, ISSM_MPI_Comm comm)
Definition: issmmpi.cpp:242
femmodel
FemModel * femmodel
Definition: esmfbinders.cpp:16