Merge lp:~simon-funke/libadjoint/online_revolve into lp:~libadjoint/libadjoint/libadjoint_python
- online_revolve
- Merge into libadjoint_python
Proposed by
Simon Funke
Status: | Merged |
---|---|
Merged at revision: | 403 |
Proposed branch: | lp:~simon-funke/libadjoint/online_revolve |
Merge into: | lp:~libadjoint/libadjoint/libadjoint_python |
Diff against target: |
1200 lines (+293/-213) 16 files modified
doc/manual/annotation.aux (+13/-11) doc/manual/data_callbacks.aux (+6/-4) doc/manual/data_callbacks.tex (+34/-18) include/libadjoint/adj_adjointer_routines.h (+4/-4) include/libadjoint/adj_constants.h (+3/-2) include/libadjoint/adj_data_structures.h (+5/-12) include/libadjoint/adj_petsc_data_structures.h (+4/-2) python/libadjoint/libadjoint.py (+80/-2) src/adj_adjointer_routines.c (+57/-92) src/adj_core.c (+9/-0) src/adj_debug.c (+3/-7) src/adj_fortran.F90 (+14/-15) src/adj_petsc_data_structures.c (+45/-9) src/tests/test_adj_forget_forward_equation.c (+3/-4) src/tests/test_checkpoint_revolve_multistage.c (+7/-16) src/tests/test_checkpoint_revolve_offline.c (+6/-15) |
To merge this branch: | bzr merge lp:~simon-funke/libadjoint/online_revolve |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Patrick Farrell | Pending | ||
Review via email: mp+89065@code.launchpad.net |
Commit message
Description of the change
Second attempt for the merge request:
- Removed var_data linked list from the adjointer. Instead the uthash iteration feature is used to loop over variables.
- Instead of providing the filename to the read/write/delete cb, I now pass in the variable and let the user decide which naming convention to use. For that I also needed to introduce a
- New callback adj_vec_delete.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'doc/manual/annotation.aux' |
2 | --- doc/manual/annotation.aux 2011-08-09 10:52:22 +0000 |
3 | +++ doc/manual/annotation.aux 2012-01-18 15:51:24 +0000 |
4 | @@ -6,16 +6,18 @@ |
5 | \@writefile{lot}{\contentsline {xchapter}{Annotating forward models}{7}{chapter.2}} |
6 | \@writefile{toc}{\contentsline {section}{\numberline {2.1}A simple example}{8}{section.2.1}} |
7 | \newlabel{sec:examples}{{2.1}{8}{A simple example\relax }{section.2.1}{}} |
8 | -\@writefile{toc}{\contentsline {section}{\numberline {2.2}Existing model code}{8}{section.2.2}} |
9 | -\@writefile{toc}{\contentsline {section}{\numberline {2.3}Annotating the model}{8}{section.2.3}} |
10 | -\newlabel{api:adj_timestep_set_times}{{2.3.1}{8}{\texttt {adj_timestep_set_times}\label {api:adj_timestep_set_times}\relax }{subsection.2.3.1}{}} |
11 | -\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.1}\texttt {adj_timestep_set_times}}{8}{subsection.2.3.1}} |
12 | -\newlabel{api:adj_timestep_set_functional_dependencies}{{2.3.2}{8}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{subsection.2.3.2}{}} |
13 | -\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.2}\texttt {adj_timestep_set_functional_dependencies}}{8}{subsection.2.3.2}} |
14 | -\newlabel{eq:functional_as_sum}{{2.1}{8}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.3.1}{}} |
15 | -\newlabel{eq:ex_functional1}{{2.2}{9}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.3.2}{}} |
16 | -\newlabel{eq:ex_functional2}{{2.3}{9}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.3.3}{}} |
17 | -\newlabel{eq:ex_functional3}{{2.4}{9}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.3.4}{}} |
18 | +\@writefile{toc}{\contentsline {section}{\numberline {2.2}A nonlinear example}{8}{section.2.2}} |
19 | +\newlabel{sec:examples}{{2.2}{8}{A nonlinear example\relax }{section.2.2}{}} |
20 | +\@writefile{toc}{\contentsline {section}{\numberline {2.3}Existing model code}{8}{section.2.3}} |
21 | +\@writefile{toc}{\contentsline {section}{\numberline {2.4}Annotating the model}{8}{section.2.4}} |
22 | +\newlabel{api:adj_timestep_set_times}{{2.4.1}{8}{\texttt {adj_timestep_set_times}\label {api:adj_timestep_set_times}\relax }{subsection.2.4.1}{}} |
23 | +\@writefile{toc}{\contentsline {subsection}{\numberline {2.4.1}\texttt {adj_timestep_set_times}}{8}{subsection.2.4.1}} |
24 | +\newlabel{api:adj_timestep_set_functional_dependencies}{{2.4.2}{8}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{subsection.2.4.2}{}} |
25 | +\@writefile{toc}{\contentsline {subsection}{\numberline {2.4.2}\texttt {adj_timestep_set_functional_dependencies}}{8}{subsection.2.4.2}} |
26 | +\newlabel{eq:functional_as_sum}{{2.1}{9}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.4.1}{}} |
27 | +\newlabel{eq:ex_functional1}{{2.2}{9}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.4.2}{}} |
28 | +\newlabel{eq:ex_functional2}{{2.3}{9}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.4.3}{}} |
29 | +\newlabel{eq:ex_functional3}{{2.4}{9}{\texttt {adj_timestep_set_functional_dependencies}\label {api:adj_timestep_set_functional_dependencies}\relax }{equation.2.4.4}{}} |
30 | \@setckpt{annotation}{ |
31 | \setcounter{page}{10} |
32 | \setcounter{equation}{6} |
33 | @@ -27,7 +29,7 @@ |
34 | \setcounter{mpfootnote}{0} |
35 | \setcounter{part}{0} |
36 | \setcounter{chapter}{2} |
37 | -\setcounter{section}{3} |
38 | +\setcounter{section}{4} |
39 | \setcounter{subsection}{2} |
40 | \setcounter{subsubsection}{0} |
41 | \setcounter{paragraph}{0} |
42 | |
43 | === modified file 'doc/manual/data_callbacks.aux' |
44 | --- doc/manual/data_callbacks.aux 2011-11-15 22:32:33 +0000 |
45 | +++ doc/manual/data_callbacks.aux 2012-01-18 15:51:24 +0000 |
46 | @@ -43,10 +43,12 @@ |
47 | \@writefile{toc}{\contentsline {subsubsection}{\numberline {3.1.3.7}\texttt {ADJ_VEC_SET_RANDOM_CB}}{17}{subsubsection.3.1.3.7}} |
48 | \newlabel{api:ADJ_VEC_DOT_PRODUCT_CB}{{3.1.3.8}{17}{\texttt {ADJ_VEC_DOT_PRODUCT_CB}\label {api:ADJ_VEC_DOT_PRODUCT_CB}\relax }{subsubsection.3.1.3.8}{}} |
49 | \@writefile{toc}{\contentsline {subsubsection}{\numberline {3.1.3.8}\texttt {ADJ_VEC_DOT_PRODUCT_CB}}{17}{subsubsection.3.1.3.8}} |
50 | -\newlabel{api:ADJ_VEC_TO_FILE_CB}{{3.1.3.9}{18}{\texttt {ADJ_VEC_TO_FILE_CB}\label {api:ADJ_VEC_TO_FILE_CB}\relax }{subsubsection.3.1.3.9}{}} |
51 | -\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.1.3.9}\texttt {ADJ_VEC_TO_FILE_CB}}{18}{subsubsection.3.1.3.9}} |
52 | -\newlabel{api:ADJ_VEC_FROM_FILE_CB}{{3.1.3.10}{18}{\texttt {ADJ_VEC_FROM_FILE_CB}\label {api:ADJ_VEC_FROM_FILE_CB}\relax }{subsubsection.3.1.3.10}{}} |
53 | -\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.1.3.10}\texttt {ADJ_VEC_FROM_FILE_CB}}{18}{subsubsection.3.1.3.10}} |
54 | +\newlabel{api:ADJ_VEC_WRITE_CB}{{3.1.3.9}{18}{\texttt {ADJ_VEC_WRITE_CB}\label {api:ADJ_VEC_WRITE_CB}\relax }{subsubsection.3.1.3.9}{}} |
55 | +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.1.3.9}\texttt {ADJ_VEC_WRITE_CB}}{18}{subsubsection.3.1.3.9}} |
56 | +\newlabel{api:ADJ_VEC_READ_CB}{{3.1.3.10}{18}{\texttt {ADJ_VEC_READ_CB}\label {api:ADJ_VEC_READ_CB}\relax }{subsubsection.3.1.3.10}{}} |
57 | +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.1.3.10}\texttt {ADJ_VEC_READ_CB}}{18}{subsubsection.3.1.3.10}} |
58 | +\newlabel{api:ADJ_VEC_DELETE_CB}{{3.1.3.11}{18}{\texttt {ADJ_VEC_DELETE_CB}\label {api:ADJ_VEC_DELETE_CB}\relax }{subsubsection.3.1.3.11}{}} |
59 | +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.1.3.11}\texttt {ADJ_VEC_DELETE_CB}}{18}{subsubsection.3.1.3.11}} |
60 | \@writefile{toc}{\contentsline {subsection}{\numberline {3.1.4}Matrix callbacks}{18}{subsection.3.1.4}} |
61 | \newlabel{sec:matrix_callbacks}{{3.1.4}{18}{Matrix callbacks\relax }{subsection.3.1.4}{}} |
62 | \newlabel{api:ADJ_MAT_DUPLICATE_CB}{{3.1.4.1}{18}{\texttt {ADJ_MAT_DUPLICATE_CB}\label {api:ADJ_MAT_DUPLICATE_CB}\relax }{subsubsection.3.1.4.1}{}} |
63 | |
64 | === modified file 'doc/manual/data_callbacks.tex' |
65 | --- doc/manual/data_callbacks.tex 2011-11-03 10:49:53 +0000 |
66 | +++ doc/manual/data_callbacks.tex 2012-01-18 15:51:24 +0000 |
67 | @@ -332,40 +332,56 @@ |
68 | activated on an \refapi{adj_block} with \refapi{adj_block_set_test_hermitian}, |
69 | or on an \refapi{adj_nonlinear_block} with \\\refapi{adj_nonlinear_block_set_test_hermitian}. |
70 | |
71 | -\defapiss{ADJ_VEC_TO_FILE_CB} |
72 | -\begin{boxwithtitle}{\texttt{ADJ_VEC_TO_FILE_CB}} |
73 | +\defapiss{ADJ_VEC_WRITE_CB} |
74 | +\begin{boxwithtitle}{\texttt{ADJ_VEC_WRITE_CB}} |
75 | \begin{minipage}{\columnwidth} |
76 | \begin{ccode} |
77 | - void (*vec_to_file)(adj_vector x, char* filename); |
78 | + void (*vec_write)(adj_variable var, adj_vector x); |
79 | \end{ccode} |
80 | \begin{fortrancode} |
81 | - subroutine adj_vec_to_file(x, filename) |
82 | + subroutine adj_vec_write(var, x) |
83 | + type(adj_variable), intent(in), value :: var |
84 | type(adj_vector), intent(in), value :: x |
85 | - character(kind=c_char), dimension(ADJ_NAME_LEN), intent(in) :: filename |
86 | - end subroutine adj_vec_to_file |
87 | + end subroutine adj_vec_write |
88 | \end{fortrancode} |
89 | \end{minipage} |
90 | \end{boxwithtitle} |
91 | -This data callback saves the provided vector into a file named \texttt{filename} on disk. |
92 | +This data callback saves the provided vector containing variable \texttt{var} to disk. |
93 | |
94 | When necessary: If a checkpointing scheme is used. |
95 | |
96 | - |
97 | -\defapiss{ADJ_VEC_FROM_FILE_CB} |
98 | -\begin{boxwithtitle}{\texttt{ADJ_VEC_FROM_FILE_CB}} |
99 | +\defapiss{ADJ_VEC_READ_CB} |
100 | +\begin{boxwithtitle}{\texttt{ADJ_VEC_READ_CB}} |
101 | \begin{minipage}{\columnwidth} |
102 | \begin{ccode} |
103 | - void (*vec_from_file)(adj_vector* x, char *filename); |
104 | + void (*vec_read)(adj_variable var, adj_vector* x); |
105 | \end{ccode} |
106 | \begin{fortrancode} |
107 | - subroutine adj_vec_from_file(x, filename) |
108 | + subroutine adj_vec_read(var, x) |
109 | + type(adj_variable), intent(in), value :: var |
110 | type(adj_vector), intent(out) :: x |
111 | - character(kind=c_char), dimension(ADJ_NAME_LEN), intent(in) :: filename |
112 | - end subroutine adj_vec_from_file |
113 | -\end{fortrancode} |
114 | -\end{minipage} |
115 | -\end{boxwithtitle} |
116 | -This data callback loads the vector from file \texttt{filename} on disk. |
117 | + end subroutine adj_vec_read |
118 | +\end{fortrancode} |
119 | +\end{minipage} |
120 | +\end{boxwithtitle} |
121 | +This data callback loads the vector containing variable \texttt{var} from disk. |
122 | + |
123 | +When necessary: If a checkpointing scheme is used. |
124 | + |
125 | +\defapiss{ADJ_VEC_DELETE_CB} |
126 | +\begin{boxwithtitle}{\texttt{ADJ_VEC_DELETE_CB}} |
127 | +\begin{minipage}{\columnwidth} |
128 | +\begin{ccode} |
129 | + void (*vec_delete)(adj_variable var) |
130 | +\end{ccode} |
131 | +\begin{fortrancode} |
132 | + subroutine adj_vec_delete(var) |
133 | + type(adj_variable), intent(in), value :: var |
134 | + end subroutine adj_vec_delete |
135 | +\end{fortrancode} |
136 | +\end{minipage} |
137 | +\end{boxwithtitle} |
138 | +This data callback deletes the file that stores variable \texttt{var}. |
139 | |
140 | When necessary: If a checkpointing scheme is used. |
141 | |
142 | |
143 | === modified file 'include/libadjoint/adj_adjointer_routines.h' |
144 | --- include/libadjoint/adj_adjointer_routines.h 2012-01-16 15:47:58 +0000 |
145 | +++ include/libadjoint/adj_adjointer_routines.h 2012-01-18 15:51:24 +0000 |
146 | @@ -64,12 +64,12 @@ |
147 | int adj_has_variable_value_disk(adj_adjointer* adjointer, adj_variable var); |
148 | int adj_is_variable_memory_checkpoint(adj_adjointer* adjointer, adj_variable var); |
149 | int adj_is_variable_disk_checkpoint(adj_adjointer* adjointer, adj_variable var); |
150 | -int adj_forget_variable_value(adj_adjointer* adjointer, adj_variable_data* data); |
151 | +int adj_forget_variable_value(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data); |
152 | int adj_forget_variable_value_from_memory(adj_adjointer* adjointer, adj_variable_data* data); |
153 | -int adj_forget_variable_value_from_disk(adj_adjointer* adjointer, adj_variable_data* data); |
154 | -int adj_destroy_variable_data(adj_adjointer* adjointer, adj_variable_data* data); |
155 | +int adj_forget_variable_value_from_disk(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data); |
156 | +int adj_destroy_variable_data(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data); |
157 | int adj_add_new_hash_entry(adj_adjointer* adjointer, adj_variable* var, adj_variable_data** data); |
158 | -int adj_record_variable_core_disk(adj_adjointer* adjointer, adj_variable_data* data_ptr, adj_storage_data storage); |
159 | +int adj_record_variable_core_disk(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data_ptr, adj_storage_data storage); |
160 | int adj_record_variable_core_memory(adj_adjointer* adjointer, adj_variable_data* data_ptr, adj_storage_data storage); |
161 | int adj_record_variable_compare(adj_adjointer* adjointer, adj_variable_data* data_ptr, adj_variable var, adj_storage_data storage); |
162 | |
163 | |
164 | === modified file 'include/libadjoint/adj_constants.h' |
165 | --- include/libadjoint/adj_constants.h 2011-11-10 20:59:12 +0000 |
166 | +++ include/libadjoint/adj_constants.h 2012-01-18 15:51:24 +0000 |
167 | @@ -69,8 +69,9 @@ |
168 | #define ADJ_VEC_GET_NORM_CB 16 |
169 | #define ADJ_VEC_DOT_PRODUCT_CB 17 |
170 | #define ADJ_VEC_SET_RANDOM_CB 18 |
171 | -#define ADJ_VEC_TO_FILE_CB 19 |
172 | -#define ADJ_VEC_FROM_FILE_CB 20 |
173 | +#define ADJ_VEC_WRITE_CB 19 |
174 | +#define ADJ_VEC_READ_CB 20 |
175 | +#define ADJ_VEC_DELETE_CB 21 |
176 | |
177 | #define ADJ_MAT_DUPLICATE_CB 30 |
178 | #define ADJ_MAT_AXPY_CB 31 |
179 | |
180 | === modified file 'include/libadjoint/adj_data_structures.h' |
181 | --- include/libadjoint/adj_data_structures.h 2012-01-16 15:47:58 +0000 |
182 | +++ include/libadjoint/adj_data_structures.h 2012-01-18 15:51:24 +0000 |
183 | @@ -96,12 +96,11 @@ |
184 | /* for ADJ_STORAGE_MEMORY */ |
185 | int storage_memory_type; /* ADJ_STORAGE_MEMORY_COPY or ADJ_STORAGE_MEMORY_INCREF */ |
186 | int storage_memory_has_value; |
187 | - int storage_memory_is_checkpoint; /* checkpoints are not deleted by adj_forget_forward_equation */ |
188 | + int storage_memory_is_checkpoint; /* memory checkpoints are not deleted by adj_forget_forward_equation */ |
189 | |
190 | /* for ADJ_STORAGE_DISK */ |
191 | int storage_disk_has_value; |
192 | - int storage_disk_is_checkpoint; /* checkpoints are not deleted by adj_forget_forward_equation */ |
193 | - char storage_disk_filename[ADJ_NAME_LEN]; |
194 | + int storage_disk_is_checkpoint; /* disk checkpoints are not deleted by adj_forget_forward_equation */ |
195 | |
196 | /* POD, temporal interpolation, ... */ |
197 | } adj_storage_data; |
198 | @@ -132,12 +131,6 @@ |
199 | |
200 | typedef struct |
201 | { |
202 | - adj_variable_data* firstnode; |
203 | - adj_variable_data* lastnode; |
204 | -} adj_variable_data_list; |
205 | - |
206 | -typedef struct |
207 | -{ |
208 | void (*vec_duplicate)(adj_vector x, adj_vector *newx); |
209 | void (*vec_axpy)(adj_vector *y, adj_scalar alpha, adj_vector x); |
210 | void (*vec_destroy)(adj_vector *x); |
211 | @@ -147,8 +140,9 @@ |
212 | void (*vec_get_norm)(adj_vector x, adj_scalar* norm); |
213 | void (*vec_dot_product)(adj_vector x, adj_vector y, adj_scalar* val); |
214 | void (*vec_set_random)(adj_vector* x); |
215 | - void (*vec_to_file)(adj_vector x, char* filename); |
216 | - void (*vec_from_file)(adj_vector* x, char *filename); |
217 | + void (*vec_write)(adj_variable var, adj_vector x); |
218 | + void (*vec_read)(adj_variable var, adj_vector* x); |
219 | + void (*vec_delete)(adj_variable var); |
220 | |
221 | void (*mat_duplicate)(adj_matrix matin, adj_matrix *matout); |
222 | void (*mat_axpy)(adj_matrix *Y, adj_scalar alpha, adj_matrix X); |
223 | @@ -286,7 +280,6 @@ |
224 | adj_revolve_data revolve_data; /* A data struct for revolve related information */ |
225 | |
226 | adj_variable_hash* varhash; /* The hash table for looking up information about variables */ |
227 | - adj_variable_data_list vardata; /* We also store a linked list so we can walk all our variable data */ |
228 | |
229 | int options[ADJ_NO_OPTIONS]; /* Pretty obvious */ |
230 | |
231 | |
232 | === modified file 'include/libadjoint/adj_petsc_data_structures.h' |
233 | --- include/libadjoint/adj_petsc_data_structures.h 2011-08-30 19:15:58 +0000 |
234 | +++ include/libadjoint/adj_petsc_data_structures.h 2012-01-18 15:51:24 +0000 |
235 | @@ -2,6 +2,7 @@ |
236 | #define ADJ_PETSC_DATA_STRUCTURES_H |
237 | |
238 | #include <string.h> |
239 | +#include <stdio.h> |
240 | #include <sys/time.h> |
241 | #include <sys/types.h> |
242 | #include <unistd.h> |
243 | @@ -24,8 +25,9 @@ |
244 | void petsc_vec_getnorm_proc(adj_vector vec, adj_scalar* norm); |
245 | void petsc_vec_set_random_proc(adj_vector* x); |
246 | void petsc_vec_dot_product_proc(adj_vector x, adj_vector y, adj_scalar* val); |
247 | -void petsc_vec_to_file_proc(adj_vector x, char* filename); |
248 | -void petsc_vec_from_file_proc(adj_vector* x, char* filename); |
249 | +void petsc_vec_write_proc(adj_variable var, adj_vector x); |
250 | +void petsc_vec_read_proc(adj_variable var, adj_vector* x); |
251 | +void petsc_vec_delete_proc(adj_variable var); |
252 | |
253 | void petsc_mat_getvec_proc(adj_matrix mat, adj_vector *left); |
254 | void petsc_mat_axpy_proc(adj_matrix *Y, adj_scalar alpha, adj_matrix X); |
255 | |
256 | === modified file 'python/libadjoint/libadjoint.py' |
257 | --- python/libadjoint/libadjoint.py 2012-01-16 15:47:58 +0000 |
258 | +++ python/libadjoint/libadjoint.py 2012-01-18 15:51:24 +0000 |
259 | @@ -294,10 +294,12 @@ |
260 | |
261 | class DiskStorage(Storage): |
262 | '''Wrapper class for Vectors that contains additional information for storing the vector values in memory.''' |
263 | - def __init__(self, vec): |
264 | + def __init__(self, vec, cs=False): |
265 | self.storage_data = clib.adj_storage_data() |
266 | self.c_object = self.storage_data |
267 | - clib.adj_storage_disk_incref(vec.as_adj_vector(), self.storage_data) |
268 | + clib.adj_storage_disk(vec.as_adj_vector(), self.storage_data) |
269 | + |
270 | + self.set_checkpoint(cs) |
271 | |
272 | # Ensure that the storage object always holds a reference to the vec |
273 | self.vec = vec |
274 | @@ -617,6 +619,9 @@ |
275 | self.vec_set_random_type = ctypes.CFUNCTYPE(None, ctypes.POINTER(clib.adj_vector)) |
276 | self.vec_set_values_type = ctypes.CFUNCTYPE(None, ctypes.POINTER(clib.adj_vector), ctypes.POINTER(adj_scalar)) |
277 | self.vec_get_size_type = ctypes.CFUNCTYPE(None, clib.adj_vector, ctypes.POINTER(ctypes.c_int)) |
278 | + self.vec_write_type = ctypes.CFUNCTYPE(None, clib.adj_variable, clib.adj_vector) |
279 | + self.vec_read_type = ctypes.CFUNCTYPE(None, clib.adj_variable, ctypes.POINTER(clib.adj_vector)) |
280 | + self.vec_delete_type = ctypes.CFUNCTYPE(None, clib.adj_variable) |
281 | self.mat_duplicate_type = ctypes.CFUNCTYPE(None, clib.adj_matrix, ctypes.POINTER(clib.adj_matrix)) |
282 | self.mat_destroy_type = ctypes.CFUNCTYPE(None, ctypes.POINTER(clib.adj_matrix)) |
283 | self.mat_axpy_type = ctypes.CFUNCTYPE(None, ctypes.POINTER(clib.adj_matrix), adj_scalar, clib.adj_matrix) |
284 | @@ -723,6 +728,25 @@ |
285 | finally: |
286 | references_taken.append(storage.vec) |
287 | |
288 | + # At this point we should also reregister the read and the delete callbacks. |
289 | + # Note that the initial callback implementation could not access |
290 | + # the user implementation of the read() and delete() functions, and but here we can. |
291 | + def __vec_read_callback__(adj_var, adj_vec_ptr): |
292 | + var = Variable(var=adj_var) |
293 | + y = storage.vec.__class__.read(var) |
294 | + # Increase the reference counter of the new object to protect it from deallocation at the end of the callback |
295 | + references_taken.append(y) |
296 | + adj_vec_ptr[0].ptr = python_utils.c_ptr(y) |
297 | + adj_vec_ptr[0].klass = 0 |
298 | + adj_vec_ptr[0].flags = 0 |
299 | + |
300 | + def __vec_delete_callback__(adj_var): |
301 | + var = Variable(var=adj_var) |
302 | + storage.vec.__class__.delete(var) |
303 | + |
304 | + self.__register_data_callback__('ADJ_VEC_DELETE_CB', __vec_delete_callback__) |
305 | + self.__register_data_callback__('ADJ_VEC_READ_CB', __vec_read_callback__) |
306 | + |
307 | def evaluate_functional(self, functional, timestep): |
308 | '''evaluate_functional(self, functional, timestep) |
309 | |
310 | @@ -850,6 +874,9 @@ |
311 | self.__register_data_callback__('ADJ_VEC_SET_RANDOM_CB', self.__vec_set_random_callback__) |
312 | self.__register_data_callback__('ADJ_VEC_SET_VALUES_CB', self.__vec_set_values_callback__) |
313 | self.__register_data_callback__('ADJ_VEC_GET_SIZE_CB', self.__vec_get_size_callback__) |
314 | + self.__register_data_callback__('ADJ_VEC_WRITE_CB', self.__vec_write_callback__) |
315 | + self.__register_data_callback__('ADJ_VEC_READ_CB', self.__vec_read_callback__) |
316 | + self.__register_data_callback__('ADJ_VEC_DELETE_CB', self.__vec_delete_callback__) |
317 | self.__register_data_callback__('ADJ_MAT_DUPLICATE_CB', self.__mat_duplicate_callback__) |
318 | self.__register_data_callback__('ADJ_MAT_DESTROY_CB', self.__mat_destroy_callback__) |
319 | self.__register_data_callback__('ADJ_MAT_AXPY_CB', self.__mat_axpy_callback__) |
320 | @@ -892,6 +919,9 @@ |
321 | 'ADJ_VEC_SET_RANDOM_CB': self.vec_set_random_type, |
322 | 'ADJ_VEC_SET_VALUES_CB': self.vec_set_values_type, |
323 | 'ADJ_VEC_GET_SIZE_CB': self.vec_get_size_type, |
324 | + 'ADJ_VEC_WRITE_CB': self.vec_write_type, |
325 | + 'ADJ_VEC_READ_CB': self.vec_read_type, |
326 | + "ADJ_VEC_DELETE_CB": self.vec_delete_type, |
327 | "ADJ_MAT_DUPLICATE_CB": self.mat_duplicate_type, |
328 | "ADJ_MAT_DESTROY_CB": self.mat_destroy_type, |
329 | "ADJ_MAT_AXPY_CB": self.mat_axpy_type, |
330 | @@ -1099,6 +1129,34 @@ |
331 | sz[0] = y.size() |
332 | |
333 | @staticmethod |
334 | + def __vec_write_callback__(adj_var, adj_vec): |
335 | + var = Variable(var=adj_var) |
336 | + vec = vector(adj_vec) |
337 | + vec.write(var) |
338 | + |
339 | + @staticmethod |
340 | + def __vec_read_callback__(adj_var, adj_vec_ptr): |
341 | + raise exceptions.LibadjointErrorInvalidInputs( |
342 | + 'Internal error: called vec_read callback before recording any variables.') |
343 | + |
344 | + @staticmethod |
345 | + def __vec_delete_callback__(adj_var): |
346 | + raise exceptions.LibadjointErrorInvalidInputs( |
347 | + 'Internal error: called vec_delete callback before recording any variables.') |
348 | + |
349 | + print "To be implemented" |
350 | + assert(False) |
351 | + vec = vector(adj_vec_ptr[0]) |
352 | + |
353 | + # Do the corresponding decref of the object, so that the Python GC can pick it up |
354 | + try: |
355 | + references_taken.remove(vec) |
356 | + except: |
357 | + print vec.data |
358 | + print references_taken |
359 | + raise |
360 | + |
361 | + @staticmethod |
362 | def __mat_duplicate_callback__(adj_mat, adj_mat_ptr): |
363 | mat = matrix(adj_mat) |
364 | new_mat = mat.duplicate() |
365 | @@ -1202,6 +1260,26 @@ |
366 | raise exceptions.LibadjointErrorNeedCallback( |
367 | 'Class '+self.__class__.__name__+' has no dot_product() method') |
368 | |
369 | + @staticmethod |
370 | + def read(var): |
371 | + '''This method must return a vector containing the values of var from disk.''' |
372 | + |
373 | + raise exceptions.LibadjointErrorNeedCallback( |
374 | + 'Class Vector has no read() method') |
375 | + |
376 | + @staticmethod |
377 | + def delete(var): |
378 | + '''This method must delete the vector containing the values of var from disk.''' |
379 | + |
380 | + raise exceptions.LibadjointErrorNeedCallback( |
381 | + 'Class Vector has no delete() method') |
382 | + |
383 | + def write(self, var): |
384 | + '''This method must write this vector as values of var to disk.''' |
385 | + |
386 | + raise exceptions.LibadjointErrorNeedCallback( |
387 | + 'Class '+self.__class__.__name__+' has no write() method') |
388 | + |
389 | def as_adj_vector(self): |
390 | '''as_adj_vector(self) |
391 | |
392 | |
393 | === modified file 'src/adj_adjointer_routines.c' |
394 | --- src/adj_adjointer_routines.c 2012-01-18 15:18:28 +0000 |
395 | +++ src/adj_adjointer_routines.c 2012-01-18 15:51:24 +0000 |
396 | @@ -12,8 +12,6 @@ |
397 | adjointer->timestep_data = NULL; |
398 | |
399 | adjointer->varhash = NULL; |
400 | - adjointer->vardata.firstnode = NULL; |
401 | - adjointer->vardata.lastnode = NULL; |
402 | |
403 | adjointer->callbacks.vec_duplicate = NULL; |
404 | adjointer->callbacks.vec_axpy = NULL; |
405 | @@ -24,8 +22,9 @@ |
406 | adjointer->callbacks.vec_get_norm = NULL; |
407 | adjointer->callbacks.vec_set_random = NULL; |
408 | adjointer->callbacks.vec_dot_product = NULL; |
409 | - adjointer->callbacks.vec_to_file = NULL; |
410 | - adjointer->callbacks.vec_from_file = NULL; |
411 | + adjointer->callbacks.vec_write = NULL; |
412 | + adjointer->callbacks.vec_read = NULL; |
413 | + adjointer->callbacks.vec_delete = NULL; |
414 | |
415 | adjointer->callbacks.mat_duplicate = NULL; |
416 | adjointer->callbacks.mat_axpy = NULL; |
417 | @@ -72,6 +71,7 @@ |
418 | { |
419 | int i; |
420 | int ierr; |
421 | + adj_variable_hash* varhash; |
422 | adj_variable_data* data_ptr; |
423 | adj_variable_data* data_ptr_tmp; |
424 | adj_op_callback* cb_ptr; |
425 | @@ -106,10 +106,10 @@ |
426 | free(adjointer->timestep_data); |
427 | } |
428 | |
429 | - data_ptr = adjointer->vardata.firstnode; |
430 | - while (data_ptr != NULL) |
431 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
432 | { |
433 | - ierr = adj_destroy_variable_data(adjointer, data_ptr); |
434 | + data_ptr=varhash->data; |
435 | + ierr = adj_destroy_variable_data(adjointer, varhash->variable, data_ptr); |
436 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
437 | data_ptr_tmp = data_ptr; |
438 | data_ptr = data_ptr->next; |
439 | @@ -688,11 +688,6 @@ |
440 | return adj_chkierr_auto(ADJ_ERR_NEED_VALUE); |
441 | } |
442 | |
443 | - /* Create the filename in case we need to store/load from disk */ |
444 | - char filename[ADJ_NAME_LEN]; |
445 | - adj_variable_str(var, filename, ADJ_NAME_LEN); |
446 | - strncat(filename, ".dat", 4); |
447 | - |
448 | /* Case 1: variable is on disk and we want to checkpoint it in disk */ |
449 | if ((cs == ADJ_CHECKPOINT_STORAGE_DISK) && (var_data->storage.storage_disk_has_value == ADJ_TRUE)) |
450 | { |
451 | @@ -721,12 +716,12 @@ |
452 | else if (cs == ADJ_CHECKPOINT_STORAGE_MEMORY && (var_data->storage.storage_memory_has_value != ADJ_TRUE)) |
453 | { |
454 | /* Check for the required callbacks */ |
455 | - if (adjointer->callbacks.vec_from_file == NULL) |
456 | + if (adjointer->callbacks.vec_read == NULL) |
457 | { |
458 | - strncpy(adj_error_msg, "Need the vec_from_file data callback, but it hasn't been supplied.", ADJ_ERROR_MSG_BUF); |
459 | + strncpy(adj_error_msg, "Need the ADJ_VEC_READ_CB data callback, but it hasn't been supplied.", ADJ_ERROR_MSG_BUF); |
460 | return adj_chkierr_auto(ADJ_ERR_NEED_CALLBACK); |
461 | } |
462 | - adjointer->callbacks.vec_from_file(&(var_data->storage.value), filename); |
463 | + adjointer->callbacks.vec_read(var, &(var_data->storage.value)); |
464 | var_data->storage.storage_memory_has_value=ADJ_TRUE; |
465 | |
466 | var_data->storage.storage_memory_is_checkpoint = ADJ_TRUE; |
467 | @@ -755,7 +750,7 @@ |
468 | (adjointer->revolve_data.current_action != CACTION_FIRSTRUN)) |
469 | { |
470 | adj_variable_str(equation.variable, buf, ADJ_NAME_LEN); |
471 | - snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "The adjointer and revolve are not consistent (in adj_register_equation of variable %s). This can happen when one tries to register an equation after solving the first adjoint equation.", buf); |
472 | + snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "The adjointer and revolve are not consistent (in adj_register_equation of variable %s). Did you register an equation after solving the first adjoint equation?", buf); |
473 | return adj_chkierr_auto(ADJ_ERR_REVOLVE_ERROR); |
474 | } |
475 | } |
476 | @@ -1002,15 +997,7 @@ |
477 | else if (storage.storage_memory_has_value && !data_ptr->storage.storage_memory_has_value) |
478 | return adj_record_variable_core_memory(adjointer, data_ptr, storage); |
479 | else if (storage.storage_disk_has_value && !data_ptr->storage.storage_disk_has_value) |
480 | - { |
481 | - /* Generate the filename */ |
482 | - char filename[ADJ_NAME_LEN]; |
483 | - adj_variable_str(var, filename, ADJ_NAME_LEN); |
484 | - strncat(filename, ".dat", 4); |
485 | - strncpy(storage.storage_disk_filename, filename, ADJ_NAME_LEN); |
486 | - |
487 | - return adj_record_variable_core_disk(adjointer, data_ptr, storage); |
488 | - } |
489 | + return adj_record_variable_core_disk(adjointer, var, data_ptr, storage); |
490 | else |
491 | /* Sorry for the slight mess. The easiest way to understand this block is to build a 2x2 graph of |
492 | compare and overwrite: |
493 | @@ -1044,7 +1031,7 @@ |
494 | { |
495 | int record_ierr; |
496 | |
497 | - ierr = adj_forget_variable_value(adjointer, data_ptr); |
498 | + ierr = adj_forget_variable_value(adjointer, var, data_ptr); |
499 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
500 | |
501 | record_ierr = adj_record_variable_core_memory(adjointer, data_ptr, storage); /* Overwrite the result anyway */ |
502 | @@ -1064,7 +1051,7 @@ |
503 | { |
504 | if (storage.overwrite) |
505 | { |
506 | - ierr = adj_forget_variable_value(adjointer, data_ptr); |
507 | + ierr = adj_forget_variable_value(adjointer, var, data_ptr); |
508 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
509 | return adj_record_variable_core_memory(adjointer, data_ptr, storage); |
510 | } |
511 | @@ -1131,11 +1118,11 @@ |
512 | } |
513 | |
514 | /* The core routine to record a variable to disk */ |
515 | -int adj_record_variable_core_disk(adj_adjointer* adjointer, adj_variable_data* data_ptr, adj_storage_data storage) |
516 | +int adj_record_variable_core_disk(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data_ptr, adj_storage_data storage) |
517 | { |
518 | - if (adjointer->callbacks.vec_to_file == NULL) |
519 | + if (adjointer->callbacks.vec_write == NULL) |
520 | { |
521 | - snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "You have asked to record a value to disk, but no ADJ_VEC_TO_FILE_CB callback has been provided."); |
522 | + snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "You have asked to record a value to disk, but no ADJ_VEC_WRITE_CB callback has been provided."); |
523 | return adj_chkierr_auto(ADJ_ERR_NEED_CALLBACK); |
524 | } |
525 | |
526 | @@ -1153,8 +1140,7 @@ |
527 | |
528 | data_ptr->storage.storage_disk_has_value = storage.storage_disk_has_value; |
529 | data_ptr->storage.storage_disk_is_checkpoint = storage.storage_disk_is_checkpoint; |
530 | - strncpy(data_ptr->storage.storage_disk_filename, storage.storage_disk_filename, ADJ_NAME_LEN); |
531 | - adjointer->callbacks.vec_to_file(storage.value, data_ptr->storage.storage_disk_filename); |
532 | + adjointer->callbacks.vec_write(var, storage.value); |
533 | |
534 | return ADJ_OK; |
535 | } |
536 | @@ -1315,11 +1301,14 @@ |
537 | case ADJ_VEC_SET_RANDOM_CB: |
538 | adjointer->callbacks.vec_set_random = (void(*)(adj_vector* x)) fn; |
539 | break; |
540 | - case ADJ_VEC_TO_FILE_CB: |
541 | - adjointer->callbacks.vec_to_file = (void(*)(adj_vector x, char* filename)) fn; |
542 | - break; |
543 | - case ADJ_VEC_FROM_FILE_CB: |
544 | - adjointer->callbacks.vec_from_file = (void(*)(adj_vector* x, char* filename)) fn; |
545 | + case ADJ_VEC_WRITE_CB: |
546 | + adjointer->callbacks.vec_write = (void(*)(adj_variable, adj_vector x)) fn; |
547 | + break; |
548 | + case ADJ_VEC_READ_CB: |
549 | + adjointer->callbacks.vec_read = (void(*)(adj_variable var, adj_vector* x)) fn; |
550 | + break; |
551 | + case ADJ_VEC_DELETE_CB: |
552 | + adjointer->callbacks.vec_delete = (void(*)(adj_variable var)) fn; |
553 | break; |
554 | |
555 | case ADJ_MAT_DUPLICATE_CB: |
556 | @@ -1431,6 +1420,7 @@ |
557 | |
558 | int adj_forget_adjoint_equation(adj_adjointer* adjointer, int equation) |
559 | { |
560 | + adj_variable_hash* varhash; |
561 | adj_variable_data* data; |
562 | int should_we_delete; |
563 | int i; |
564 | @@ -1439,8 +1429,8 @@ |
565 | |
566 | if (adjointer->options[ADJ_ACTIVITY] == ADJ_ACTIVITY_NOTHING) return ADJ_OK; |
567 | |
568 | - /* Dont delete any variables if we want to compare in the revolve replays */ |
569 | - if (adjointer->revolve_data.overwrite==ADJ_TRUE) |
570 | + /* Do not delete any variables if we want to compare forward variables with the revolve replay */ |
571 | + if (adjointer->revolve_data.overwrite == ADJ_TRUE) |
572 | return ADJ_OK; |
573 | |
574 | if (equation >= adjointer->nequations) |
575 | @@ -1449,9 +1439,9 @@ |
576 | return adj_chkierr_auto(ADJ_ERR_INVALID_INPUTS); |
577 | } |
578 | |
579 | - data = adjointer->vardata.firstnode; |
580 | - while (data != NULL) |
581 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
582 | { |
583 | + data = varhash->data; |
584 | if (data->storage.storage_memory_has_value || data->storage.storage_disk_has_value) |
585 | { |
586 | should_we_delete = 1; |
587 | @@ -1485,7 +1475,7 @@ |
588 | /* Forget only non-checkpoint variables */ |
589 | if (data->storage.storage_disk_has_value && !data->storage.storage_disk_is_checkpoint) |
590 | { |
591 | - ierr = adj_forget_variable_value_from_disk(adjointer, data); |
592 | + ierr = adj_forget_variable_value_from_disk(adjointer, varhash->variable, data); |
593 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
594 | } |
595 | if (data->storage.storage_memory_has_value && !data->storage.storage_memory_is_checkpoint) |
596 | @@ -1496,7 +1486,6 @@ |
597 | } |
598 | } |
599 | |
600 | - data = data->next; |
601 | } |
602 | |
603 | return ADJ_OK; |
604 | @@ -1521,6 +1510,7 @@ |
605 | */ |
606 | int adj_forget_forward_equation_until(adj_adjointer* adjointer, int equation, int last_equation) |
607 | { |
608 | + adj_variable_hash* varhash; |
609 | adj_variable_data* data; |
610 | int should_we_delete; |
611 | int i; |
612 | @@ -1534,23 +1524,16 @@ |
613 | return adj_chkierr_auto(ADJ_ERR_INVALID_INPUTS); |
614 | } |
615 | |
616 | - data = adjointer->vardata.firstnode; |
617 | - |
618 | - while (data != NULL) |
619 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
620 | { |
621 | + data = varhash->data; |
622 | /* Only forget forward variables */ |
623 | if (data->type != ADJ_FORWARD) /* Skip adjoint or TLM variables. */ |
624 | - { |
625 | - data = data->next; |
626 | continue; |
627 | - } |
628 | |
629 | /* Only forget forward variables that are computed at equations <= equation */ |
630 | if (data->equation>equation) |
631 | - { |
632 | - data = data->next; |
633 | continue; |
634 | - } |
635 | |
636 | if (data->storage.storage_memory_has_value || data->storage.storage_disk_has_value) |
637 | { |
638 | @@ -1593,7 +1576,7 @@ |
639 | /* Forget only non-checkpoint variables */ |
640 | if (data->storage.storage_disk_has_value && !data->storage.storage_disk_is_checkpoint) |
641 | { |
642 | - ierr = adj_forget_variable_value_from_disk(adjointer, data); |
643 | + ierr = adj_forget_variable_value_from_disk(adjointer, varhash->variable, data); |
644 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
645 | } |
646 | if (data->storage.storage_memory_has_value && !data->storage.storage_memory_is_checkpoint) |
647 | @@ -1604,7 +1587,6 @@ |
648 | } |
649 | } |
650 | |
651 | - data = data->next; |
652 | } |
653 | |
654 | return ADJ_OK; |
655 | @@ -1612,6 +1594,7 @@ |
656 | |
657 | int adj_forget_tlm_equation(adj_adjointer* adjointer, int equation) |
658 | { |
659 | + adj_variable_hash* varhash; |
660 | adj_variable_data* data; |
661 | int should_we_delete; |
662 | int i; |
663 | @@ -1625,16 +1608,13 @@ |
664 | return adj_chkierr_auto(ADJ_ERR_INVALID_INPUTS); |
665 | } |
666 | |
667 | - data = adjointer->vardata.firstnode; |
668 | - |
669 | - while (data != NULL) |
670 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
671 | { |
672 | + data = varhash->data; |
673 | + |
674 | /* Only forget forward variables */ |
675 | if (data->type != ADJ_TLM) /* Skip anything other than TLM variables.. */ |
676 | - { |
677 | - data = data->next; |
678 | continue; |
679 | - } |
680 | |
681 | if (data->storage.storage_memory_has_value || data->storage.storage_disk_has_value) |
682 | { |
683 | @@ -1679,7 +1659,6 @@ |
684 | } |
685 | } |
686 | |
687 | - data = data->next; |
688 | } |
689 | |
690 | return ADJ_OK; |
691 | @@ -1803,12 +1782,14 @@ |
692 | /* Disk storage */ |
693 | else if(data_ptr->storage.storage_disk_has_value) |
694 | { |
695 | - if (adjointer->callbacks.vec_from_file == NULL) |
696 | + if (adjointer->callbacks.vec_read == NULL) |
697 | { |
698 | - snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "You have asked to get a value from disk, but no ADJ_VEC_FROM_FILE_CB callback has been provided."); |
699 | + snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "You have asked to get a value from disk, but no ADJ_VEC_READ_CB callback has been provided."); |
700 | return adj_chkierr_auto(ADJ_ERR_NEED_CALLBACK); |
701 | } |
702 | - adjointer->callbacks.vec_from_file(value, data_ptr->storage.storage_disk_filename); |
703 | + adjointer->callbacks.vec_read(var, value); |
704 | + data_ptr->storage.storage_memory_has_value = ADJ_TRUE; |
705 | + data_ptr->storage.value = *value; |
706 | } |
707 | return ADJ_OK; |
708 | } |
709 | @@ -1895,13 +1876,13 @@ |
710 | return data_ptr->storage.storage_memory_is_checkpoint; |
711 | } |
712 | |
713 | -int adj_forget_variable_value(adj_adjointer* adjointer, adj_variable_data* data) |
714 | +int adj_forget_variable_value(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data) |
715 | { |
716 | int ierr; |
717 | |
718 | if (data->storage.storage_disk_has_value) |
719 | { |
720 | - ierr = adj_forget_variable_value_from_disk(adjointer, data); |
721 | + ierr = adj_forget_variable_value_from_disk(adjointer, var, data); |
722 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
723 | } |
724 | if (data->storage.storage_memory_has_value) |
725 | @@ -1912,22 +1893,18 @@ |
726 | return ADJ_OK; |
727 | } |
728 | |
729 | -int adj_forget_variable_value_from_disk(adj_adjointer* adjointer, adj_variable_data* data) |
730 | +int adj_forget_variable_value_from_disk(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data) |
731 | { |
732 | - int ierr; |
733 | + if (adjointer->callbacks.vec_delete == NULL) |
734 | + { |
735 | + strncpy(adj_error_msg, "Need ADJ_VEC_DELETE_CB data callback.", ADJ_ERROR_MSG_BUF); |
736 | + return adj_chkierr_auto(ADJ_ERR_NEED_CALLBACK); |
737 | + } |
738 | |
739 | assert(data->storage.storage_disk_has_value); |
740 | - if (access(data->storage.storage_disk_filename, W_OK) == -1) { |
741 | - char buf[ADJ_NAME_LEN]; |
742 | - adj_variable_str(adjointer->equations[data->equation].variable, buf, ADJ_NAME_LEN); |
743 | - |
744 | - ierr = ADJ_ERR_INVALID_INPUTS; |
745 | - snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "Can not access variable %s in file '%s'.", buf, data->storage.storage_disk_filename); |
746 | - return adj_chkierr_auto(ierr); |
747 | - } |
748 | |
749 | data->storage.storage_disk_has_value = ADJ_FALSE; |
750 | - remove(data->storage.storage_disk_filename); |
751 | + adjointer->callbacks.vec_delete(var); |
752 | return ADJ_OK; |
753 | } |
754 | |
755 | @@ -1935,7 +1912,7 @@ |
756 | { |
757 | if (adjointer->callbacks.vec_destroy == NULL) |
758 | { |
759 | - strncpy(adj_error_msg, "Need vec_destroy data callback.", ADJ_ERROR_MSG_BUF); |
760 | + strncpy(adj_error_msg, "Need ADJ_VEC_DESTROY_CB data callback.", ADJ_ERROR_MSG_BUF); |
761 | return adj_chkierr_auto(ADJ_ERR_NEED_CALLBACK); |
762 | } |
763 | |
764 | @@ -1946,7 +1923,7 @@ |
765 | return ADJ_OK; |
766 | } |
767 | |
768 | -int adj_destroy_variable_data(adj_adjointer* adjointer, adj_variable_data* data) |
769 | +int adj_destroy_variable_data(adj_adjointer* adjointer, adj_variable var, adj_variable_data* data) |
770 | { |
771 | |
772 | if (data->ntargeting_equations > 0) |
773 | @@ -1974,7 +1951,7 @@ |
774 | } |
775 | |
776 | if (data->storage.storage_memory_has_value || data->storage.storage_disk_has_value) |
777 | - return adj_forget_variable_value(adjointer, data); |
778 | + return adj_forget_variable_value(adjointer, var, data); |
779 | |
780 | return ADJ_OK; |
781 | } |
782 | @@ -2156,18 +2133,6 @@ |
783 | ierr = adj_add_variable_data(&(adjointer->varhash), var, *data); |
784 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
785 | |
786 | - /* and add to the data list */ |
787 | - if (adjointer->vardata.firstnode == NULL) |
788 | - { |
789 | - adjointer->vardata.firstnode = *data; |
790 | - adjointer->vardata.lastnode = *data; |
791 | - } |
792 | - else |
793 | - { |
794 | - adjointer->vardata.lastnode->next = *data; |
795 | - adjointer->vardata.lastnode = *data; |
796 | - } |
797 | - |
798 | return ADJ_OK; |
799 | } |
800 | |
801 | |
802 | === modified file 'src/adj_core.c' |
803 | --- src/adj_core.c 2012-01-16 15:47:58 +0000 |
804 | +++ src/adj_core.c 2012-01-18 15:51:24 +0000 |
805 | @@ -455,6 +455,15 @@ |
806 | oldcapo = revolve_getoldcapo(adjointer->revolve_data.revolve); |
807 | capo = revolve_getcapo(adjointer->revolve_data.revolve); |
808 | |
809 | + /* If revolve advances to a timestep larger than ntimeteps-1, |
810 | + * then the user claimed in the revolve settings to solve for more timesteps then we actually did. |
811 | + */ |
812 | + if (capo > adjointer->ntimesteps-1) |
813 | + { |
814 | + snprintf(adj_error_msg, ADJ_ERROR_MSG_BUF, "Revolve expected %i timesteps but only %i were annotated.", capo+1, adjointer->ntimesteps); |
815 | + return adj_chkierr_auto(ADJ_ERR_INVALID_INPUTS); |
816 | + } |
817 | + |
818 | ierr = adj_timestep_start_equation(adjointer, oldcapo, &start_eqn); |
819 | if (ierr != ADJ_OK) return adj_chkierr_auto(ierr); |
820 | ierr = adj_timestep_end_equation(adjointer, capo-1, &end_eqn); |
821 | |
822 | === modified file 'src/adj_debug.c' |
823 | --- src/adj_debug.c 2011-11-10 22:18:55 +0000 |
824 | +++ src/adj_debug.c 2012-01-18 15:51:24 +0000 |
825 | @@ -136,6 +136,7 @@ |
826 | |
827 | if (cp_num>0) |
828 | { |
829 | + adj_variable_hash* varhash; |
830 | adj_variable_data* data; |
831 | |
832 | /* The first checkpoint equation must be zero, otherwise */ |
833 | @@ -147,16 +148,12 @@ |
834 | } |
835 | |
836 | /* Check we have the required variables for the adjoint equations */ |
837 | - data = adjointer->vardata.firstnode; |
838 | - /* Loop over every variable */ |
839 | - while (data != NULL) |
840 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
841 | { |
842 | + data = varhash->data; |
843 | /* We are only interested in forward variables */ |
844 | if (data->equation < 0) |
845 | - { |
846 | - data = data->next; |
847 | continue; |
848 | - } |
849 | |
850 | /* Find out in which checkpoint slot the variable is computed */ |
851 | for (cp_iter=0; cp_iter < cp_num-1; cp_iter++) |
852 | @@ -187,7 +184,6 @@ |
853 | } |
854 | } |
855 | |
856 | - data = data->next; |
857 | } |
858 | } |
859 | |
860 | |
861 | === modified file 'src/adj_fortran.F90' |
862 | --- src/adj_fortran.F90 2012-01-16 15:47:58 +0000 |
863 | +++ src/adj_fortran.F90 2012-01-18 15:51:24 +0000 |
864 | @@ -71,8 +71,9 @@ |
865 | type(c_funptr) :: vec_get_norm |
866 | type(c_funptr) :: vec_dot_product |
867 | type(c_funptr) :: vec_set_random |
868 | - type(c_funptr) :: vec_to_file |
869 | - type(c_funptr) :: vec_from_file |
870 | + type(c_funptr) :: vec_write |
871 | + type(c_funptr) :: vec_read |
872 | + type(c_funptr) :: vec_delete |
873 | |
874 | type(c_funptr) :: mat_duplicate |
875 | type(c_funptr) :: mat_axpy |
876 | @@ -81,11 +82,6 @@ |
877 | type(c_funptr) :: solve |
878 | end type adj_data_callbacks |
879 | |
880 | - type, bind(c) :: adj_variable_data_list |
881 | - type(c_ptr) :: firstnode |
882 | - type(c_ptr) :: lastnode |
883 | - end type adj_variable_data_list |
884 | - |
885 | type, bind(c) :: adj_op_callback_list |
886 | type(c_ptr) :: firstnode |
887 | type(c_ptr) :: lastnode |
888 | @@ -135,7 +131,6 @@ |
889 | type(adj_revolve_data) :: revolve_data |
890 | |
891 | type(c_ptr) :: varhash |
892 | - type(adj_variable_data_list) :: vardata |
893 | |
894 | integer(kind=c_int), dimension(ADJ_NO_OPTIONS) :: options |
895 | |
896 | @@ -176,7 +171,6 @@ |
897 | |
898 | integer(kind=c_int) :: storage_disk_has_value |
899 | integer(kind=c_int) :: storage_disk_is_checkpoint |
900 | - character(kind=c_char), dimension(ADJ_NAME_LEN) :: storage_disk_filename |
901 | end type adj_storage_data |
902 | |
903 | type, bind(c) :: adj_dictionary |
904 | @@ -245,17 +239,22 @@ |
905 | type(adj_vector), intent(inout) :: x |
906 | end subroutine adj_vec_set_random |
907 | |
908 | - subroutine adj_vec_to_file(x, filename) bind(c) |
909 | + subroutine adj_vec_write(var, x) bind(c) |
910 | use libadjoint_data_structures |
911 | + type(adj_variable), intent(in), value :: var |
912 | type(adj_vector), intent(in), value :: x |
913 | - character(kind=c_char), dimension(ADJ_NAME_LEN), intent(in) :: filename |
914 | - end subroutine adj_vec_to_file |
915 | + end subroutine adj_vec_write |
916 | |
917 | - subroutine adj_vec_from_file(x, filename) bind(c) |
918 | + subroutine adj_vec_read(var, x) bind(c) |
919 | use libadjoint_data_structures |
920 | + type(adj_variable), intent(in), value :: var |
921 | type(adj_vector), intent(out) :: x |
922 | - character(kind=c_char), dimension(ADJ_NAME_LEN), intent(in) :: filename |
923 | - end subroutine adj_vec_from_file |
924 | + end subroutine adj_vec_read |
925 | + |
926 | + subroutine adj_vec_delete(var) bind(c) |
927 | + use libadjoint_data_structures |
928 | + type(adj_variable), intent(in), value :: var |
929 | + end subroutine adj_vec_delete |
930 | |
931 | subroutine adj_mat_duplicate_proc(matin, matout) bind(c) |
932 | ! Allocate a new matrix, using a given matrix as the model |
933 | |
934 | === modified file 'src/adj_petsc_data_structures.c' |
935 | --- src/adj_petsc_data_structures.c 2011-11-10 21:04:41 +0000 |
936 | +++ src/adj_petsc_data_structures.c 2012-01-18 15:51:24 +0000 |
937 | @@ -21,9 +21,11 @@ |
938 | adj_chkierr(ierr); |
939 | ierr = adj_register_data_callback(adjointer, ADJ_VEC_DOT_PRODUCT_CB,(void (*)(void)) petsc_vec_dot_product_proc); |
940 | adj_chkierr(ierr); |
941 | - ierr = adj_register_data_callback(adjointer, ADJ_VEC_TO_FILE_CB,(void (*)(void)) petsc_vec_to_file_proc); |
942 | - adj_chkierr(ierr); |
943 | - ierr = adj_register_data_callback(adjointer, ADJ_VEC_FROM_FILE_CB,(void (*)(void)) petsc_vec_from_file_proc); |
944 | + ierr = adj_register_data_callback(adjointer, ADJ_VEC_WRITE_CB,(void (*)(void)) petsc_vec_write_proc); |
945 | + adj_chkierr(ierr); |
946 | + ierr = adj_register_data_callback(adjointer, ADJ_VEC_READ_CB,(void (*)(void)) petsc_vec_read_proc); |
947 | + adj_chkierr(ierr); |
948 | + ierr = adj_register_data_callback(adjointer, ADJ_VEC_DELETE_CB,(void (*)(void)) petsc_vec_delete_proc); |
949 | adj_chkierr(ierr); |
950 | ierr = adj_register_data_callback(adjointer, ADJ_MAT_AXPY_CB,(void (*)(void)) petsc_mat_axpy_proc); |
951 | adj_chkierr(ierr); |
952 | @@ -75,6 +77,24 @@ |
953 | #endif |
954 | } |
955 | |
956 | +void petsc_vec_delete_proc(adj_variable var) |
957 | +{ |
958 | +#ifdef HAVE_PETSC |
959 | + /* Generate the filename */ |
960 | + char filename[ADJ_NAME_LEN]; |
961 | + adj_variable_str(var, filename, ADJ_NAME_LEN); |
962 | + strncat(filename, ".dat", 4); |
963 | + |
964 | + if (access(filename, W_OK) == -1) { |
965 | + char buf[ADJ_NAME_LEN]; |
966 | + adj_variable_str(var, buf, ADJ_NAME_LEN); |
967 | + fprintf(stderr, "Can remove variable %s in file '%s'. File does not exist.", buf, filename); |
968 | + } |
969 | + |
970 | + remove(filename); |
971 | +#endif |
972 | +} |
973 | + |
974 | void petsc_vec_getnorm_proc(adj_vector x, adj_scalar* norm) |
975 | { |
976 | #ifdef HAVE_PETSC |
977 | @@ -100,9 +120,13 @@ |
978 | #endif |
979 | } |
980 | |
981 | -void petsc_vec_to_file_proc(adj_vector x, char* filename) |
982 | +void petsc_vec_write_proc(adj_variable var, adj_vector x) |
983 | { |
984 | #ifdef HAVE_PETSC |
985 | + /* Generate the filename */ |
986 | + char filename[ADJ_NAME_LEN]; |
987 | + adj_variable_str(var, filename, ADJ_NAME_LEN); |
988 | + strncat(filename, ".dat", 4); |
989 | |
990 | if (access(filename, W_OK) == 0) |
991 | { |
992 | @@ -110,8 +134,8 @@ |
993 | } |
994 | |
995 | PetscViewer viewer; |
996 | - PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_WRITE,&viewer); |
997 | - VecView(petsc_vec_from_adj_vector(x),viewer); |
998 | + PetscViewerBinaryOpen(PETSC_COMM_WORLD, filename, FILE_MODE_WRITE, &viewer); |
999 | + VecView(petsc_vec_from_adj_vector(x), viewer); |
1000 | PetscViewerDestroy(viewer); |
1001 | #else |
1002 | (void) x; |
1003 | @@ -119,13 +143,25 @@ |
1004 | #endif |
1005 | } |
1006 | |
1007 | -void petsc_vec_from_file_proc(adj_vector *x, char* filename) |
1008 | +void petsc_vec_read_proc(adj_variable var, adj_vector *x) |
1009 | { |
1010 | #ifdef HAVE_PETSC |
1011 | + /* Generate the filename */ |
1012 | + char filename[ADJ_NAME_LEN]; |
1013 | + adj_variable_str(var, filename, ADJ_NAME_LEN); |
1014 | + strncat(filename, ".dat", 4); |
1015 | + |
1016 | + if (access(filename, W_OK) == -1) { |
1017 | + char buf[ADJ_NAME_LEN]; |
1018 | + adj_variable_str(var, buf, ADJ_NAME_LEN); |
1019 | + |
1020 | + fprintf(stderr, "Can not access variable %s in file '%s'.", buf, filename); |
1021 | + } |
1022 | + |
1023 | Vec *vec=(Vec*) malloc(sizeof(Vec)); |
1024 | PetscViewer viewer; |
1025 | - PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_READ,&viewer); |
1026 | - VecLoad(viewer,PETSC_NULL,vec); |
1027 | + PetscViewerBinaryOpen(PETSC_COMM_WORLD, filename, FILE_MODE_READ, &viewer); |
1028 | + VecLoad(viewer, PETSC_NULL, vec); |
1029 | PetscViewerDestroy(viewer); |
1030 | *x = petsc_vec_to_adj_vector(vec); |
1031 | #else |
1032 | |
1033 | === modified file 'src/tests/test_adj_forget_forward_equation.c' |
1034 | --- src/tests/test_adj_forget_forward_equation.c 2011-11-28 10:38:19 +0000 |
1035 | +++ src/tests/test_adj_forget_forward_equation.c 2012-01-18 15:51:24 +0000 |
1036 | @@ -36,6 +36,7 @@ |
1037 | adj_storage_data storage; |
1038 | char filename_fwd[ADJ_NAME_LEN]; |
1039 | int checkpoint_strategy[steps]; |
1040 | + adj_variable_hash *varhash; |
1041 | adj_variable_data *var_data; |
1042 | |
1043 | ierr = adj_create_adjointer(&adjointer); |
1044 | @@ -144,13 +145,11 @@ |
1045 | } |
1046 | |
1047 | /* Besides checkpoints, no variables should be stored anymore ... */ |
1048 | - var_data=adjointer.vardata.firstnode; |
1049 | - while(var_data!=NULL) |
1050 | + for(varhash=adjointer.varhash; varhash != NULL; varhash=varhash->hh.next) |
1051 | { |
1052 | + var_data = varhash->data; |
1053 | adj_test_assert(var_data->storage.storage_memory_has_value==var_data->storage.storage_memory_is_checkpoint, "Should have worked"); |
1054 | adj_test_assert(var_data->storage.storage_disk_has_value==var_data->storage.storage_disk_is_checkpoint, "Should have worked"); |
1055 | - |
1056 | - var_data=var_data->next; |
1057 | } |
1058 | |
1059 | } |
1060 | |
1061 | === modified file 'src/tests/test_checkpoint_revolve_multistage.c' |
1062 | --- src/tests/test_checkpoint_revolve_multistage.c 2011-11-28 10:38:19 +0000 |
1063 | +++ src/tests/test_checkpoint_revolve_multistage.c 2012-01-18 15:51:24 +0000 |
1064 | @@ -552,6 +552,7 @@ |
1065 | int ierr, i, nb_matched_variables, found_match; |
1066 | int duplicates=0; /* Number of variables that are recorded on both disk and memory */ |
1067 | adj_variable var; |
1068 | + adj_variable_hash *varhash; |
1069 | adj_variable_data* data_ptr; |
1070 | char var_name[ADJ_NAME_LEN]; |
1071 | |
1072 | @@ -560,20 +561,15 @@ |
1073 | * If the variable name matches with a variable name in the expectation list, |
1074 | * we check if the the storage and checkpoint type match. |
1075 | */ |
1076 | - data_ptr=adjointer->vardata.firstnode; |
1077 | - while (data_ptr!=NULL) |
1078 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
1079 | { |
1080 | + data_ptr=varhash->data; |
1081 | if (data_ptr->equation<0) /* Ignore adjoint variables */ |
1082 | - { |
1083 | - data_ptr=data_ptr->next; |
1084 | continue; |
1085 | - } |
1086 | + |
1087 | if ((data_ptr->storage.storage_memory_has_value!=ADJ_TRUE) && |
1088 | (data_ptr->storage.storage_disk_has_value!=ADJ_TRUE)) /* Ignore variables that are not recorded */ |
1089 | - { |
1090 | - data_ptr=data_ptr->next; |
1091 | continue; |
1092 | - } |
1093 | |
1094 | var = adjointer->equations[data_ptr->equation].variable; |
1095 | ierr = adj_variable_str(var, var_name, ADJ_NAME_LEN); |
1096 | @@ -640,7 +636,6 @@ |
1097 | return ADJ_ERR_NEED_VALUE; |
1098 | } |
1099 | |
1100 | - data_ptr=data_ptr->next; |
1101 | } |
1102 | |
1103 | /* At this point we know that the recorded variables is a subset of |
1104 | @@ -648,23 +643,19 @@ |
1105 | * expected variables equal, from which we now that both sets are |
1106 | * equivalent. |
1107 | */ |
1108 | - data_ptr=adjointer->vardata.firstnode; |
1109 | nb_matched_variables=0; /* Number of checkpoint variables in adjointer */ |
1110 | |
1111 | - while (data_ptr!=NULL) |
1112 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
1113 | { |
1114 | - if (data_ptr->equation<0) /* Ignore adjoint variables */ |
1115 | - { |
1116 | - data_ptr=data_ptr->next; |
1117 | + data_ptr=varhash->data; |
1118 | + if (data_ptr->equation<0) /* Ignore adjoint variables */ |
1119 | continue; |
1120 | - } |
1121 | |
1122 | if (data_ptr->storage.storage_memory_has_value) |
1123 | nb_matched_variables++; |
1124 | if (data_ptr->storage.storage_disk_has_value) |
1125 | nb_matched_variables++; |
1126 | |
1127 | - data_ptr=data_ptr->next; |
1128 | } |
1129 | |
1130 | /* We expect the number of expected and recorded variables to be the same */ |
1131 | |
1132 | === modified file 'src/tests/test_checkpoint_revolve_offline.c' |
1133 | --- src/tests/test_checkpoint_revolve_offline.c 2011-11-28 10:38:19 +0000 |
1134 | +++ src/tests/test_checkpoint_revolve_offline.c 2012-01-18 15:51:24 +0000 |
1135 | @@ -489,6 +489,7 @@ |
1136 | int ierr, i, nb_matched_variables, found_match; |
1137 | int duplicates=0; /* Number of variables that are recorded on both disk and memory */ |
1138 | adj_variable var; |
1139 | + adj_variable_hash *varhash; |
1140 | adj_variable_data* data_ptr; |
1141 | char var_name[ADJ_NAME_LEN]; |
1142 | |
1143 | @@ -497,20 +498,15 @@ |
1144 | * If the variable name matches with a variable name in the expectation list, |
1145 | * we check if the the storage and checkpoint type match. |
1146 | */ |
1147 | - data_ptr=adjointer->vardata.firstnode; |
1148 | - while (data_ptr!=NULL) |
1149 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
1150 | { |
1151 | + data_ptr=varhash->data; |
1152 | if (data_ptr->equation<0) /* Ignore adjoint variables */ |
1153 | - { |
1154 | - data_ptr=data_ptr->next; |
1155 | continue; |
1156 | - } |
1157 | + |
1158 | if ((data_ptr->storage.storage_memory_has_value!=ADJ_TRUE) && |
1159 | (data_ptr->storage.storage_disk_has_value!=ADJ_TRUE)) /* Ignore variables that are not recorded */ |
1160 | - { |
1161 | - data_ptr=data_ptr->next; |
1162 | continue; |
1163 | - } |
1164 | |
1165 | var = adjointer->equations[data_ptr->equation].variable; |
1166 | ierr = adj_variable_str(var, var_name, ADJ_NAME_LEN); |
1167 | @@ -577,7 +573,6 @@ |
1168 | return ADJ_ERR_NEED_VALUE; |
1169 | } |
1170 | |
1171 | - data_ptr=data_ptr->next; |
1172 | } |
1173 | |
1174 | /* At this point we know that the recorded variables is a subset of |
1175 | @@ -585,23 +580,19 @@ |
1176 | * expected variables equal, from which we now that both sets are |
1177 | * equivalent. |
1178 | */ |
1179 | - data_ptr=adjointer->vardata.firstnode; |
1180 | nb_matched_variables=0; /* Number of checkpoint variables in adjointer */ |
1181 | |
1182 | - while (data_ptr!=NULL) |
1183 | + for(varhash=adjointer->varhash; varhash != NULL; varhash=varhash->hh.next) |
1184 | { |
1185 | + data_ptr=varhash->data; |
1186 | if (data_ptr->equation<0) /* Ignore adjoint variables */ |
1187 | - { |
1188 | - data_ptr=data_ptr->next; |
1189 | continue; |
1190 | - } |
1191 | |
1192 | if (data_ptr->storage.storage_memory_has_value) |
1193 | nb_matched_variables++; |
1194 | if (data_ptr->storage.storage_disk_has_value) |
1195 | nb_matched_variables++; |
1196 | |
1197 | - data_ptr=data_ptr->next; |
1198 | } |
1199 | |
1200 | /* We expect the number of expected and recorded variables to be the same */ |