@@ -323,10 +323,8 @@ def computeConcentration(self,source,enforce_nonnegative=False):
323323
324324 self .conc = concentration
325325 return c
326-
327-
328326
329- class AdjointAdvectionDiffusionReactionModel (AdjointAdvectionDiffusionModel , AdvectionDiffusionReactionModel ):
327+ class AdjointAdvectionDiffusionReactionModel (AdvectionDiffusionReactionModel , AdjointAdvectionDiffusionModel ):
330328 def computeAdjoint (self ,H ):
331329 """
332330 Runs the backward PDE (adjoint problem)
@@ -359,6 +357,69 @@ def computeAdjoint(self,H):
359357 v [- i - 1 ,1 :Nx - 1 ,1 :Ny - 1 ]= v [- i ,1 :Nx - 1 ,1 :Ny - 1 ] + dt * ( H [- i ,1 :Nx - 1 ,1 :Ny - 1 ]+ u [0 ][- i ,1 :Nx - 1 ,1 :Ny - 1 ]* (v [- i ,2 :Nx ,1 :Ny - 1 ]- v [- i ,0 :Nx - 2 ,1 :Ny - 1 ])/ (2 * dx ) + u [1 ][- i ,1 :Nx - 1 ,1 :Ny - 1 ]* (v [- i ,1 :Nx - 1 ,2 :Ny ]- v [- i ,1 :Nx - 1 ,0 :Ny - 2 ] )/ (2 * dy )+ k_0 * (v [- i ,2 :Nx ,1 :Ny - 1 ]- 2 * v [- i ,1 :Nx - 1 ,1 :Ny - 1 ] + v [- i ,0 :Nx - 2 ,1 :Ny - 1 ])/ dx2 + k_0 * (v [- i ,1 :Nx - 1 ,2 :Ny ]- 2 * v [- i ,1 :Nx - 1 ,1 :Ny - 1 ] + v [- i ,1 :Nx - 1 ,0 :Ny - 2 ])/ dy2 - R * v [- i ,1 :Nx - 1 ,1 :Ny - 1 ])
360358 return v
361359
360+ class SimpleODEModel (AdvectionDiffusionModel ):
361+ def __init__ (self ,boundary ,resolution ,kernel ,noiseSD ,sensormodel ,N_feat = 25 ,spatial_averaging = 1.0 ):
362+ """
363+ The Advection Diffusion Reaction Model.
364+
365+ At the moment we assume a 3d grid [time, x, y].
366+
367+ Parameters:
368+ boundary = a two element tuple of the corners of the grid. e.g. ([0,0,0],[10,10,10])
369+ resolution = a list of the grid size in each dimension. e.g. [10,20,20]
370+ kernel = the kernel to use
371+ noiseSD = the noise standard deviation
372+ sensormodel = an instatiation of a SensorModel class that implements the getHs method.
373+ N_feat = number of fourier features
374+ spatial_averaging = how big the volume the sensor measures (default 0.001).
375+ u = wind speed
376+ k_0 = diffusion constant
377+ R = reaction constant
378+ """
379+ super ().__init__ (boundary ,resolution ,kernel ,noiseSD ,sensormodel ,N_feat ,spatial_averaging )
380+
381+
382+ def computeConcentration (self ,source ,enforce_nonnegative = False ):
383+ """
384+ Computes concentrations.
385+ Arguments:
386+ source == forcing function (shape: Nt x Nx x Ny). Can either be generated by ... or determine manually.
387+ enforce_nonnegative = default False,. Setting to true will force concentration to be non-negative each iteration.
388+ returns array of concentrations (shape: Nt x Nx x Ny), given source. (also saved it in self.concentration)
389+ """
390+ #source = self.source
391+
392+ #get the grid step sizes, their squares and the size of the grid
393+ dt ,dx ,dy ,dx2 ,dy2 ,Nt ,Nx ,Ny = self .getGridStepSize ()
394+
395+ c = np .zeros (((self .resolution )))
396+
397+ c [0 ,:,:]= 0
398+
399+ for i in range (0 ,Nt - 1 ):
400+ # Internal Calc
401+ c [i + 1 ,:,:]= c [i ,:,:] + dt * (source [i ,:,:])
402+ if enforce_nonnegative : c [c < 0 ]= 0
403+ concentration = c
404+
405+ self .conc = concentration
406+ return c
407+
408+ class AdjointSimpleODEModel (SimpleODEModel ,AdjointAdvectionDiffusionModel ):
409+ def computeAdjoint (self ,H ):
410+ """
411+ Runs the backward PDE (adjoint problem)
412+ Gets called for an observation instance (H).
413+ (v is the result of the adjoint operation)
414+ """
415+ dt ,dx ,dy ,dx2 ,dy2 ,Nt ,Nx ,Ny = self .getGridStepSize ()
416+
417+ v = np .zeros (((Nt ,Nx ,Ny )))
418+ v [- 1 ,:,:]= 0.0
419+ for i in range (1 ,Nt ): #TODO might be better to rewrite as range(Nt-1,1,-1)...
420+ #Internal calculation (not on the boundary)
421+ v [- i - 1 ,:,:]= v [- i ,:,:] + dt * ( H [- i ,:,:])
422+ return v
362423
363424class MCMCAdvectionDiffusionModel (AdvectionDiffusionModel ):
364425 def computeLikelihood (self ,pred_y ,act_y ):
0 commit comments