xref: /libCEED/tests/t522-operator-f.f90 (revision 15910d16b955338d1102d4e730fc58bca8f202b9)
1b6faaefaSjeremylt!-----------------------------------------------------------------------
2b6faaefaSjeremylt!
3b6faaefaSjeremylt! Header with common subroutine
4b6faaefaSjeremylt!
5b6faaefaSjeremylt      include 't320-basis-f.h'
6b6faaefaSjeremylt!-----------------------------------------------------------------------
7b6faaefaSjeremylt      subroutine setup(ctx,q,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,&
8b6faaefaSjeremylt&           u15,u16,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15,v16,ierr)
9b6faaefaSjeremylt      real*8 ctx
10b6faaefaSjeremylt      real*8 u1(1)
11b6faaefaSjeremylt      real*8 u2(1)
12b6faaefaSjeremylt      real*8 v1(1)
13b6faaefaSjeremylt      real*8 w
14b6faaefaSjeremylt      integer q,ierr
15b6faaefaSjeremylt
16b6faaefaSjeremylt      do i=1,q
17b6faaefaSjeremylt        w = u1(i)/(u2(i+0*q)*u2(i+3*q)-u2(i+1*q)*u2(i+2*q))
18b6faaefaSjeremylt        v1(i+0*q)=w*(u2(i+2*q)*u2(i+2*q)+u2(i+3*q)*u2(i+3*q))
19b6faaefaSjeremylt        v1(i+1*q)=w*(u2(i+0*q)*u2(i+0*q)+u2(i+1*q)*u2(i+1*q))
20b6faaefaSjeremylt        v1(i+2*q)=w*(u2(i+0*q)*u2(i+2*q)+u2(i+1*q)*u2(i+3*q))
21b6faaefaSjeremylt      enddo
22b6faaefaSjeremylt
23b6faaefaSjeremylt      ierr=0
24b6faaefaSjeremylt      end
25b6faaefaSjeremylt!-----------------------------------------------------------------------
26b6faaefaSjeremylt      subroutine diff(ctx,q,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,&
27b6faaefaSjeremylt&           u15,u16,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15,v16,ierr)
28b6faaefaSjeremylt      real*8 ctx
29b6faaefaSjeremylt      real*8 u1(1)
30b6faaefaSjeremylt      real*8 u2(1)
31b6faaefaSjeremylt      real*8 v1(1)
32b6faaefaSjeremylt      integer q,ierr
33b6faaefaSjeremylt
34b6faaefaSjeremylt      do i=1,q
35b6faaefaSjeremylt        v1(i+0*q)=u1(i+0*q)*u2(i+0*q)+u1(i+2*q)*u2(i+1*q)
36b6faaefaSjeremylt        v1(i+1*q)=u1(i+2*q)*u2(i+0*q)+u1(i+1*q)*u2(i+1*q)
37b6faaefaSjeremylt      enddo
38b6faaefaSjeremylt
39b6faaefaSjeremylt      ierr=0
40b6faaefaSjeremylt      end
41b6faaefaSjeremylt!-----------------------------------------------------------------------
42b6faaefaSjeremylt      program test
43b6faaefaSjeremylt
44b6faaefaSjeremylt      include 'ceedf.h'
45b6faaefaSjeremylt
46b6faaefaSjeremylt      integer ceed,err,i,j,k
4761dbc9d2Sjeremylt      integer imode
4861dbc9d2Sjeremylt      parameter(imode=ceed_noninterlaced)
49*15910d16Sjeremylt      integer stridesqdtet(3),stridesqdhex(3)
50*15910d16Sjeremylt      integer erestrictxtet,erestrictutet,erestrictqditet,&
51*15910d16Sjeremylt&             erestrictxhex,erestrictuhex,erestrictqdihex
52b6faaefaSjeremylt      integer bxtet,butet,bxhex,buhex
53b6faaefaSjeremylt      integer qf_setuptet,qf_difftet,qf_setuphex,qf_diffhex
54b6faaefaSjeremylt      integer op_setuptet,op_difftet,op_setuphex,op_diffhex,op_setup,op_diff
55b6faaefaSjeremylt      integer qdatatet,qdatahex,x,u,v
56b6faaefaSjeremylt      integer nelemtet,nelemhex,ptet,phex,qtet,qhex,d
57b6faaefaSjeremylt      integer row,col,offset
58b6faaefaSjeremylt      parameter(nelemtet=6)
59b6faaefaSjeremylt      parameter(ptet=6)
60b6faaefaSjeremylt      parameter(qtet=4)
61b6faaefaSjeremylt      parameter(nelemhex=6)
62b6faaefaSjeremylt      parameter(phex=3)
63b6faaefaSjeremylt      parameter(qhex=4)
64b6faaefaSjeremylt      parameter(d=2)
65b6faaefaSjeremylt      integer ndofs,nqptstet,nqptshex,nqpts,nx,ny,nxtet,nytet,nxhex
66b6faaefaSjeremylt      parameter(nx=3)
67b6faaefaSjeremylt      parameter(ny=3)
68b6faaefaSjeremylt      parameter(nxtet=3)
69b6faaefaSjeremylt      parameter(nytet=1)
70b6faaefaSjeremylt      parameter(nxhex=3)
71b6faaefaSjeremylt      parameter(ndofs=(nx*2+1)*(ny*2+1))
72b6faaefaSjeremylt      parameter(nqptstet=nelemtet*qtet)
73b6faaefaSjeremylt      parameter(nqptshex=nelemhex*qhex*qhex)
74b6faaefaSjeremylt      parameter(nqpts=nqptstet+nqptshex)
75b6faaefaSjeremylt      integer indxtet(nelemtet*ptet),indxhex(nelemhex*phex*phex)
76b6faaefaSjeremylt      real*8 arrx(d*ndofs)
77b6faaefaSjeremylt      integer*8 voffset,xoffset
78b6faaefaSjeremylt
79b6faaefaSjeremylt      real*8 qref(d*qtet)
80b6faaefaSjeremylt      real*8 qweight(qtet)
81b6faaefaSjeremylt      real*8 interp(ptet*qtet)
82b6faaefaSjeremylt      real*8 grad(d*ptet*qtet)
83b6faaefaSjeremylt
84b6faaefaSjeremylt      real*8 hv(ndofs)
85b6faaefaSjeremylt      real*8 total
86b6faaefaSjeremylt
87b6faaefaSjeremylt      character arg*32
88b6faaefaSjeremylt
89b6faaefaSjeremylt      external setup,diff
90b6faaefaSjeremylt
91b6faaefaSjeremylt      call getarg(1,arg)
92b6faaefaSjeremylt
93b6faaefaSjeremylt      call ceedinit(trim(arg)//char(0),ceed,err)
94b6faaefaSjeremylt
95b6faaefaSjeremylt! DoF Coordinates
96b6faaefaSjeremylt      do i=0,ny*2
97b6faaefaSjeremylt        do j=0,nx*2
98b6faaefaSjeremylt          arrx(i+j*(ny*2+1)+0*ndofs+1)=1.d0*i/(2*ny)
99b6faaefaSjeremylt          arrx(i+j*(ny*2+1)+1*ndofs+1)=1.d0*j/(2*nx)
100b6faaefaSjeremylt        enddo
101b6faaefaSjeremylt      enddo
102b6faaefaSjeremylt
103b6faaefaSjeremylt      call ceedvectorcreate(ceed,d*ndofs,x,err)
104b6faaefaSjeremylt      xoffset=0
105b6faaefaSjeremylt      call ceedvectorsetarray(x,ceed_mem_host,ceed_use_pointer,arrx,xoffset,err)
106b6faaefaSjeremylt
107b6faaefaSjeremylt! Qdata Vectors
108b6faaefaSjeremylt      call ceedvectorcreate(ceed,nqptstet*d*(d+1)/2,qdatatet,err)
109b6faaefaSjeremylt      call ceedvectorcreate(ceed,nqptshex*d*(d+1)/2,qdatahex,err)
110b6faaefaSjeremylt
111b6faaefaSjeremylt! Tet Elements
112b6faaefaSjeremylt      do i=0,2
113b6faaefaSjeremylt        col=mod(i,nx)
114b6faaefaSjeremylt        row=i/nx
115b6faaefaSjeremylt        offset=col*2+row*(nx*2+1)*2
116b6faaefaSjeremylt
117b6faaefaSjeremylt        indxtet(i*2*ptet+1)=2+offset
118b6faaefaSjeremylt        indxtet(i*2*ptet+2)=9+offset
119b6faaefaSjeremylt        indxtet(i*2*ptet+3)=16+offset
120b6faaefaSjeremylt        indxtet(i*2*ptet+4)=1+offset
121b6faaefaSjeremylt        indxtet(i*2*ptet+5)=8+offset
122b6faaefaSjeremylt        indxtet(i*2*ptet+6)=0+offset
123b6faaefaSjeremylt
124b6faaefaSjeremylt        indxtet(i*2*ptet+7)=14+offset
125b6faaefaSjeremylt        indxtet(i*2*ptet+8)=7+offset
126b6faaefaSjeremylt        indxtet(i*2*ptet+9)=0+offset
127b6faaefaSjeremylt        indxtet(i*2*ptet+10)=15+offset
128b6faaefaSjeremylt        indxtet(i*2*ptet+11)=8+offset
129b6faaefaSjeremylt        indxtet(i*2*ptet+12)=16+offset
130b6faaefaSjeremylt      enddo
131b6faaefaSjeremylt
132b6faaefaSjeremylt! -- Restrictions
13361dbc9d2Sjeremylt      call ceedelemrestrictioncreate(ceed,imode,nelemtet,ptet,ndofs,d,&
134a8d32208Sjeremylt     & ceed_mem_host,ceed_use_pointer,indxtet,erestrictxtet,err)
135b6faaefaSjeremylt
13661dbc9d2Sjeremylt      call ceedelemrestrictioncreate(ceed,imode,nelemtet,ptet,ndofs,1,&
137a8d32208Sjeremylt     & ceed_mem_host,ceed_use_pointer,indxtet,erestrictutet,err)
1387509a596Sjeremylt      stridesqdtet=[1,qtet,qtet*d*(d+1)/2]
1397509a596Sjeremylt      call ceedelemrestrictioncreatestrided(ceed,nelemtet,qtet,nqptstet,&
1407509a596Sjeremylt     & d*(d+1)/2,stridesqdtet,erestrictqditet,err)
141b6faaefaSjeremylt
142b6faaefaSjeremylt! -- Bases
143b6faaefaSjeremylt      call buildmats(qref,qweight,interp,grad)
144b6faaefaSjeremylt      call ceedbasiscreateh1(ceed,ceed_triangle,d,ptet,qtet,interp,grad,qref,&
145b6faaefaSjeremylt     & qweight,bxtet,err)
146b6faaefaSjeremylt      call buildmats(qref,qweight,interp,grad)
147b6faaefaSjeremylt      call ceedbasiscreateh1(ceed,ceed_triangle,1,ptet,qtet,interp,grad,qref,&
148b6faaefaSjeremylt     & qweight,butet,err)
149b6faaefaSjeremylt
150b6faaefaSjeremylt! -- QFunctions
151b6faaefaSjeremylt      call ceedqfunctioncreateinterior(ceed,1,setup,&
152b6faaefaSjeremylt     &SOURCE_DIR&
153a05f9790Sjeremylt     &//'t522-operator.h:setup'//char(0),qf_setuptet,err)
154b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_setuptet,'_weight',1,ceed_eval_weight,err)
155b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_setuptet,'dx',d*d,ceed_eval_grad,err)
156b6faaefaSjeremylt      call ceedqfunctionaddoutput(qf_setuptet,'rho',d*(d+1)/2,ceed_eval_none,&
157b6faaefaSjeremylt     & err)
158b6faaefaSjeremylt
159b6faaefaSjeremylt      call ceedqfunctioncreateinterior(ceed,1,diff,&
160b6faaefaSjeremylt     &SOURCE_DIR&
161a05f9790Sjeremylt     &//'t522-operator.h:diff'//char(0),qf_difftet,err)
162b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_difftet,'rho',d*(d+1)/2,ceed_eval_none,err)
163b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_difftet,'u',d,ceed_eval_grad,err)
164b6faaefaSjeremylt      call ceedqfunctionaddoutput(qf_difftet,'v',d,ceed_eval_grad,err)
165b6faaefaSjeremylt
166b6faaefaSjeremylt! -- Operators
167b6faaefaSjeremylt! ---- Setup Tet
168442e7f0bSjeremylt      call ceedoperatorcreate(ceed,qf_setuptet,ceed_qfunction_none,&
169442e7f0bSjeremylt     & ceed_qfunction_none,op_setuptet,err)
170*15910d16Sjeremylt      call ceedoperatorsetfield(op_setuptet,'_weight',&
171*15910d16Sjeremylt     & ceed_elemrestriction_none,bxtet,ceed_vector_none,err)
172b6faaefaSjeremylt      call ceedoperatorsetfield(op_setuptet,'dx',erestrictxtet,&
173a8d32208Sjeremylt     & bxtet,ceed_vector_active,err)
174b6faaefaSjeremylt      call ceedoperatorsetfield(op_setuptet,'rho',erestrictqditet,&
175a8d32208Sjeremylt     & ceed_basis_collocated,qdatatet,err)
176b6faaefaSjeremylt! ---- diff Tet
177442e7f0bSjeremylt      call ceedoperatorcreate(ceed,qf_difftet,ceed_qfunction_none,&
178442e7f0bSjeremylt     & ceed_qfunction_none,op_difftet,err)
179b6faaefaSjeremylt      call ceedoperatorsetfield(op_difftet,'rho',erestrictqditet,&
180a8d32208Sjeremylt     & ceed_basis_collocated,qdatatet,err)
181b6faaefaSjeremylt      call ceedoperatorsetfield(op_difftet,'u',erestrictutet,&
182a8d32208Sjeremylt     & butet,ceed_vector_active,err)
183b6faaefaSjeremylt      call ceedoperatorsetfield(op_difftet,'v',erestrictutet,&
184a8d32208Sjeremylt     & butet,ceed_vector_active,err)
185b6faaefaSjeremylt
186b6faaefaSjeremylt! Hex Elements
187b6faaefaSjeremylt      do i=0,nelemhex-1
188b6faaefaSjeremylt        col=mod(i,nx)
189b6faaefaSjeremylt        row=i/nx
190b6faaefaSjeremylt        offset=(nxtet*2+1)*(nytet*2)*(1+row)+col*2
191b6faaefaSjeremylt        do j=0,phex-1
192b6faaefaSjeremylt          do k=0,phex-1
193b6faaefaSjeremylt            indxhex(phex*(phex*i+k)+j+1)=offset+k*(nxhex*2+1)+j
194b6faaefaSjeremylt          enddo
195b6faaefaSjeremylt        enddo
196b6faaefaSjeremylt      enddo
197b6faaefaSjeremylt
198b6faaefaSjeremylt! -- Restrictions
19961dbc9d2Sjeremylt      call ceedelemrestrictioncreate(ceed,imode,nelemhex,phex*phex,ndofs,d,&
200b6faaefaSjeremylt     & ceed_mem_host,ceed_use_pointer,indxhex,erestrictxhex,err)
201b6faaefaSjeremylt
20261dbc9d2Sjeremylt      call ceedelemrestrictioncreate(ceed,imode,nelemhex,phex*phex,ndofs,1,&
203b6faaefaSjeremylt     & ceed_mem_host,ceed_use_pointer,indxhex,erestrictuhex,err)
2047509a596Sjeremylt      stridesqdhex=[1,qhex*qhex,qhex*qhex*d*(d+1)/2]
2057509a596Sjeremylt      call ceedelemrestrictioncreatestrided(ceed,nelemhex,qhex*qhex,&
2067509a596Sjeremylt     & nqptshex,d*(d+1)/2,stridesqdhex,erestrictqdihex,err)
207b6faaefaSjeremylt
208b6faaefaSjeremylt! -- Bases
209b6faaefaSjeremylt      call ceedbasiscreatetensorh1lagrange(ceed,d,d,phex,qhex,ceed_gauss,&
210b6faaefaSjeremylt     & bxhex,err)
211b6faaefaSjeremylt      call ceedbasiscreatetensorh1lagrange(ceed,d,1,phex,qhex,ceed_gauss,&
212b6faaefaSjeremylt     & buhex,err)
213b6faaefaSjeremylt
214b6faaefaSjeremylt! -- QFunctions
215b6faaefaSjeremylt      call ceedqfunctioncreateinterior(ceed,1,setup,&
216b6faaefaSjeremylt     &SOURCE_DIR&
217872c4ebbSjeremylt     &//'t522-operator.h:setup'//char(0),qf_setuphex,err)
218b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_setuphex,'_weight',1,ceed_eval_weight,err)
219b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_setuphex,'dx',d*d,ceed_eval_grad,err)
220b6faaefaSjeremylt      call ceedqfunctionaddoutput(qf_setuphex,'rho',d*(d+1)/2,ceed_eval_none,&
221b6faaefaSjeremylt     & err)
222b6faaefaSjeremylt
223b6faaefaSjeremylt      call ceedqfunctioncreateinterior(ceed,1,diff,&
224b6faaefaSjeremylt     &SOURCE_DIR&
225872c4ebbSjeremylt     &//'t522-operator.h:diff'//char(0),qf_diffhex,err)
226b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_diffhex,'rho',d*(d+1)/2,ceed_eval_none,err)
227b6faaefaSjeremylt      call ceedqfunctionaddinput(qf_diffhex,'u',d,ceed_eval_grad,err)
228b6faaefaSjeremylt      call ceedqfunctionaddoutput(qf_diffhex,'v',d,ceed_eval_grad,err)
229b6faaefaSjeremylt
230b6faaefaSjeremylt! -- Operators
231b6faaefaSjeremylt! ---- Setup Hex
232442e7f0bSjeremylt      call ceedoperatorcreate(ceed,qf_setuphex,ceed_qfunction_none,&
233442e7f0bSjeremylt     & ceed_qfunction_none,op_setuphex,err)
234*15910d16Sjeremylt      call ceedoperatorsetfield(op_setuphex,'_weight',&
235*15910d16Sjeremylt     & ceed_elemrestriction_none,bxhex,ceed_vector_none,err)
236b6faaefaSjeremylt      call ceedoperatorsetfield(op_setuphex,'dx',erestrictxhex,&
237a8d32208Sjeremylt     & bxhex,ceed_vector_active,err)
238b6faaefaSjeremylt      call ceedoperatorsetfield(op_setuphex,'rho',erestrictqdihex,&
239a8d32208Sjeremylt     & ceed_basis_collocated,qdatahex,err)
240b6faaefaSjeremylt! ---- diff Hex
241442e7f0bSjeremylt      call ceedoperatorcreate(ceed,qf_diffhex,ceed_qfunction_none,&
242442e7f0bSjeremylt     & ceed_qfunction_none,op_diffhex,err)
243b6faaefaSjeremylt      call ceedoperatorsetfield(op_diffhex,'rho',erestrictqdihex,&
244a8d32208Sjeremylt     & ceed_basis_collocated,qdatahex,err)
245b6faaefaSjeremylt      call ceedoperatorsetfield(op_diffhex,'u',erestrictuhex,&
246a8d32208Sjeremylt     & buhex,ceed_vector_active,err)
247b6faaefaSjeremylt      call ceedoperatorsetfield(op_diffhex,'v',erestrictuhex,&
248a8d32208Sjeremylt     & buhex,ceed_vector_active,err)
249b6faaefaSjeremylt
250b6faaefaSjeremylt! Composite Operators
251b6faaefaSjeremylt      call ceedcompositeoperatorcreate(ceed,op_setup,err)
252b6faaefaSjeremylt      call ceedcompositeoperatoraddsub(op_setup,op_setuptet,err)
253b6faaefaSjeremylt      call ceedcompositeoperatoraddsub(op_setup,op_setuphex,err)
254b6faaefaSjeremylt
255b6faaefaSjeremylt      call ceedcompositeoperatorcreate(ceed,op_diff,err)
256b6faaefaSjeremylt      call ceedcompositeoperatoraddsub(op_diff,op_difftet,err)
257b6faaefaSjeremylt      call ceedcompositeoperatoraddsub(op_diff,op_diffhex,err)
258b6faaefaSjeremylt
259b6faaefaSjeremylt! Apply Setup Operator
260e97ff134Sjeremylt      call ceedoperatorapply(op_setup,x,ceed_vector_none,&
261e97ff134Sjeremylt     & ceed_request_immediate,err)
262b6faaefaSjeremylt
263b6faaefaSjeremylt! Apply diff Operator
264b6faaefaSjeremylt      call ceedvectorcreate(ceed,ndofs,u,err)
265b6faaefaSjeremylt      call ceedvectorsetvalue(u,1.d0,err)
266b6faaefaSjeremylt      call ceedvectorcreate(ceed,ndofs,v,err)
267b6faaefaSjeremylt
268b6faaefaSjeremylt      call ceedoperatorapply(op_diff,u,v,ceed_request_immediate,err)
269b6faaefaSjeremylt
270b6faaefaSjeremylt! Check Output
271b6faaefaSjeremylt      call ceedvectorgetarrayread(v,ceed_mem_host,hv,voffset,err)
272b6faaefaSjeremylt      do i=1,ndofs
273b6faaefaSjeremylt      if (abs(hv(voffset+i))>1.0d-14) then
274b6faaefaSjeremylt! LCOV_EXCL_START
275b6faaefaSjeremylt        write(*,*) 'Computed: ',total,' != True: 0.0'
276b6faaefaSjeremylt! LCOV_EXCL_STOP
277b6faaefaSjeremylt      endif
278b6faaefaSjeremylt      enddo
279b6faaefaSjeremylt      call ceedvectorrestorearrayread(v,hv,voffset,err)
280b6faaefaSjeremylt
281b6faaefaSjeremylt! Cleanup
282b6faaefaSjeremylt      call ceedqfunctiondestroy(qf_setuptet,err)
283b6faaefaSjeremylt      call ceedqfunctiondestroy(qf_difftet,err)
284b6faaefaSjeremylt      call ceedoperatordestroy(op_setuptet,err)
285b6faaefaSjeremylt      call ceedoperatordestroy(op_difftet,err)
286b6faaefaSjeremylt      call ceedqfunctiondestroy(qf_setuphex,err)
287b6faaefaSjeremylt      call ceedqfunctiondestroy(qf_diffhex,err)
288b6faaefaSjeremylt      call ceedoperatordestroy(op_setuphex,err)
289b6faaefaSjeremylt      call ceedoperatordestroy(op_diffhex,err)
290b6faaefaSjeremylt      call ceedoperatordestroy(op_setup,err)
291b6faaefaSjeremylt      call ceedoperatordestroy(op_diff,err)
292b6faaefaSjeremylt      call ceedelemrestrictiondestroy(erestrictutet,err)
293b6faaefaSjeremylt      call ceedelemrestrictiondestroy(erestrictxtet,err)
294b6faaefaSjeremylt      call ceedelemrestrictiondestroy(erestrictqditet,err)
295b6faaefaSjeremylt      call ceedelemrestrictiondestroy(erestrictuhex,err)
296b6faaefaSjeremylt      call ceedelemrestrictiondestroy(erestrictxhex,err)
297b6faaefaSjeremylt      call ceedelemrestrictiondestroy(erestrictqdihex,err)
298b6faaefaSjeremylt      call ceedbasisdestroy(butet,err)
299b6faaefaSjeremylt      call ceedbasisdestroy(bxtet,err)
300b6faaefaSjeremylt      call ceedbasisdestroy(buhex,err)
301b6faaefaSjeremylt      call ceedbasisdestroy(bxhex,err)
302b6faaefaSjeremylt      call ceedvectordestroy(x,err)
303b6faaefaSjeremylt      call ceedvectordestroy(u,err)
304b6faaefaSjeremylt      call ceedvectordestroy(v,err)
305b6faaefaSjeremylt      call ceedvectordestroy(qdatatet,err)
306b6faaefaSjeremylt      call ceedvectordestroy(qdatahex,err)
307b6faaefaSjeremylt      call ceeddestroy(ceed,err)
308b6faaefaSjeremylt      end
309b6faaefaSjeremylt!-----------------------------------------------------------------------
310