Thank you for the response. After looking at the second link specifically, is not the coupling formally performed in my inserted code by "eq = eq1 & eq2 & eq3 & eq4 & eq5 & eq6"? I made some changes to my code to be able to assess one case where I do know the initial/boundary conditions and have an expected output. This allowed me to make some simplifications and remove one equation altogether leading to 5 coupled equations:
[X] The conditions are: N1(z,0) = 0.5*np.sin(theta0) P1(z,0) = 0.5*np.cos(theta0) P2(z,0)= 0. E1(L,t) = 0. E2(L,t) = 0. where t = [0,500] and z = [0,L] where L is defined in the code. [code] from fipy import * import numpy as np import matplotlib.pyplot as plt #constants & parameters omega = 2.*np.pi*(1612.*10**(6)) eps = 8.85*10**(-12) c = 3.*(10**8) hbar = (6.626*10**(-34))/(2*np.pi) eta = 0.01 #inversion factior nn = 10.**7 #population density n = eta*nn #inverted population density lambdaOH = c/(1612.*10**(6)) #wavelength gamma = 1.282*(10.**(-11)) Tsp = 1./gamma TR = 604800. T1 = 210.*TR T2 = 210.*TR L = (Tsp/TR)*(8.*np.pi)/((3.*(lambdaOH**2.))*n) d = (3.*eps*c*hbar*(lambdaOH**2)*gamma/(4.*np.pi*omega))**0.5 radius = np.sqrt(lambdaOH*L/np.pi) A = np.pi*(radius**2) V = (np.pi*(radius**2))*L NN = n*V #total inverted population constant3 = (omega*TR*NN*(d**2)/(2*c*hbar*eps*V)) Fn = 1. # Fresnel number = A/(lambdaOH*L) Lp = 1. Ldiff = Fn*L/0.35 theta0 = 4.7*(10**(-5)) zmax = L #final length of z domain tmax = 500. #final length of t domain if __name__ == "__main__": steps = nz = nt = 50 else: steps = nz = nt = 10 mesh = Grid2D(nx=nz, ny=nt, dx=(zmax/nz), dy=(tmax/nt)) #dx = dz, dy = dt z, t = mesh.cellCenters dz = (zmax/nz) dt = (tmax/nt) N1 = CellVariable(name=r"$N_1$", mesh=mesh, hasOld=True, value=0.0) #value here changes every element P1 = CellVariable(name=r"$P_1$", mesh=mesh, hasOld=True) #and sets values of function.old argument! P2 = CellVariable(name=r"$P_2$", mesh=mesh, hasOld=True) E1 = CellVariable(name=r"$E_1$", mesh=mesh, hasOld=True, value = 0.) E2 = CellVariable(name=r"$E_2$", mesh=mesh, hasOld=True) N1.constrain(0.5*np.sin(theta0), where=mesh.facesBottom) P1.constrain(0.5*np.cos(theta0), where=mesh.facesBottom) P2.constrain(0., where=mesh.facesBottom) E1.constrain(0., where=mesh.facesRight) E2.constrain(0., where=mesh.facesRight) if __name__ == "__main__": viewer = Viewer(vars=(N1, P1, P2, E1, E2)) # , datamin=0., datamax=1.) CoEff = CellVariable(mesh=mesh, value=(1), rank=1) #vector with values 1 dN1dt = -2.*(P2*E1 + P1*E2) - N1/(T1/TR) dP1dt = 2.*E2*N1 - P1/(T2/TR) dP2dt = 2.*E1*N1 - P2/(T2/TR) dE1dz = constant3*P2 - E1/Ldiff dE2dz = constant3*P1 - E2/Ldiff eq1 = (TransientTerm(var=N1) == dN1dt) eq2 = (TransientTerm(var=P1) == dP1dt) eq3 = (TransientTerm(var=P2) == dP2dt) eq4 = (CentralDifferenceConvectionTerm(coeff=CoEff,var=E1) == dE1dz) eq5 = (CentralDifferenceConvectionTerm(coeff=CoEff,var=E2) == dE2dz) eq = eq1 & eq2 & eq3 & eq4 & elapsedt = 0. i = 0 while elapsedt < tmax: N1.updateOld() P1.updateOld() P2.updateOld() E1.updateOld() E2.updateOld() i = i + 1 T = i*(tmax/nt)#min(100, numerix.exp(dexp)) elapsedt += dt eq.solve(dt=T) I_SR_scaled = (0.5*c*eps*(E1**2 + E2**2)) I_SR = I_SR_scaled/((d*TR/hbar)**2) I_nc = (2./3.)*hbar*omega/(A*TR) #(should be) equivalent to I_nc IntensityRatio = (I_SR/(NN*I_nc))/0.001 t = np.linspace(0,tmax,nt) IntensityRatioZequalL = [] i = 0 while i < (nt): A = IntensityRatio[(nz - 1) + i*nt] IntensityRatioZequalL.append(A) i = i + 1 Intensity = np.array(IntensityRatioZequalL) fig = plt.figure(1) plt.plot(t,Intensity,'k:',linewidth = 1.5) plt.xlabel('t (ns)') plt.ylabel(r"$ \frac {I_{SR}}{NI_{nc}}$") plt.show() [/code] On top of the existing documentation, I've been following the example of cahnHiliard.mesh2Dcoupled closely and notice their mesh is x and y while I am assigning mine as z (I am only considering one spatial variable at the moment) and t. Without making the grid 2D, I was unable to set boundary conditions for z and t. (I assume the partial derivative with respect to z is set by the CentralDifferenceConvectionTerm term.) Although when running the code, it appears the z variable is not being integrated at each new step. I am also applying boundary conditions at the end of the sample interval (i.e. at z = L) which may affect how the variables are updated. Any thoughts on how to ensure both z and t are being updated appropriately in this case? ________________________________ From: fipy-boun...@nist.gov <fipy-boun...@nist.gov> on behalf of Guyer, Jonathan E. Dr. (Fed) <jonathan.gu...@nist.gov> Sent: June 27, 2016 10:45:55 AM To: FIPY Subject: Re: FiPy for nonlinear, coupled PDEs in multiple independent variables You have nothing here to actually couple the equations. At a minimum, you need to sweep each timestep to convergence. See: http://www.ctcms.nist.gov/fipy/documentation/FAQ.html#iterations-timesteps-and-sweeps-oh-my Better would be to formally couple the equations. See: http://www.ctcms.nist.gov/fipy/documentation/USAGE.html#coupledequations > On Jun 16, 2016, at 2:48 PM, Abhilash Mathews <amath...@uwo.ca> wrote: > > I have recently been trying to solve these 6 coupled, nonlinear PDEs of the > general form: > <Screen Shot 2016-06-16 at 2.23.03 PM.png> > (where N_1,N_2,P_1,P_2,E_1, and E_2 are the solutions sought; t and z are the > independent variables (only 2 at the moment); a,b,c,d,e,f,g,h and k are > positive constants) > > I have set the parameters and constants equal to 1 for simplicity in this > example. Here is my code: > > [code] > from fipy import * > import numpy as np > > zmax = 10. #final length of z domain > tmax = 5. #final length of t domain > if __name__ == "__main__": > steps = nz = nt = 100 #number of elements, where dn is increments, so > range is nn*dn > #for the nth variable assessed > else: > steps = nz = nt = 10 > > mesh = Grid2D(nx=nz, ny=nt, dx=(zmax/nz), dy=(tmax/nt)) #dx = dz, dy = dt > z, t = mesh.cellCenters #pairs z and t to make a grid with nz by nt elements > dz = (zmax/nz) > dt = (tmax/nt) > > N1 = CellVariable(name=r"$N_1$", mesh=mesh, hasOld=True, value=0.0) #value > here changes every element > N2 = CellVariable(name=r"$N_2$", mesh=mesh, hasOld=True) #and sets values of > function.old argument! > P1 = CellVariable(name=r"$P_1$", mesh=mesh, hasOld=True) > P2 = CellVariable(name=r"$P_2$", mesh=mesh, hasOld=True) > E1 = CellVariable(name=r"$E_1$", mesh=mesh, hasOld=True, value = 0.) > E2 = CellVariable(name=r"$E_2$", mesh=mesh, hasOld=True) > #The CellVariables are in a grid with nz by nt elements, which corresponds to > #a particular point on the grid > #The CellVariables are in the format of F = F(z,t) where t is constant for nz > elements > #and then changes for the nz + 1 element to the next step t + dt > > for i in range(nz): #this sets initial condition at t = dt (not necessarily t > = 0) > N1[i] = 0.01 > N2[i] = 0. > P1[i] = 1. > P2[i] = 0. > E1[i] = 0. > E2[i] = 1. > > #sets boundary condition at z = dz (not necessarily z = 0) > N1[::nt] = 0.01*(np.e**(-2.*np.log(2)*((t[::nt]-t[0])**2))) > N2[::nt] = 0. > P1[::nt] = 1.*(np.e**(-2.*np.log(2)*((t[::nt]-t[0])**2))) > P2[::nt] = 0. > E1[::nt] = 0. > E2[::nt] = 1.*(np.e**(-2.*np.log(2)*((t[::nt]-t[0])**2))) > > if __name__ == "__main__": > viewer = Viewer(vars=(N1, N2, P1, P2, E1, E2)) # , datamin=0., datamax=1.) > > #constants & parameters > hbar = 1 > c = 1 > eps = 1 > omega = 1. > d = 1. > T1 = 1. > T2 = 1. > Ldiff = 1. > > CoEff = CellVariable(mesh=mesh, value=(1), rank=1) #vector with values 1 > > dN1dt = (-2/hbar)*(P2*E1 + P1*E2) - N1/T1 > dN2dt = -N2/T1 > dP1dt = (2*(d**2)/hbar)*(E2*N1 - E1*N2) - P1/T2 > dP2dt = (2*(d**2)/hbar)*(E1*N1 + E2*N2) - P2/T2 > dE1dz = (omega/(2*eps*c))*P2 - E1/Ldiff > dE2dz = (omega/(2*eps*c))*P1 - E2/Ldiff > > eq1 = (TransientTerm(var=N1) == dN1dt) > eq2 = (TransientTerm(var=N2) == dN2dt) > eq3 = (TransientTerm(var=P1) == dP1dt) > eq4 = (TransientTerm(var=P2) == dP2dt) > eq5 = (CentralDifferenceConvectionTerm(coeff=CoEff,var=E1) == dE1dz) > eq6 = (CentralDifferenceConvectionTerm(coeff=CoEff,var=E2) == dE2dz) > > eq = eq1 & eq2 & eq3 & eq4 & eq5 & eq6 > > elapsedt = 0. > i = 0 > > while elapsedt < tmax: > N1.updateOld() > N2.updateOld() > P1.updateOld() > P2.updateOld() > E1.updateOld() > E2.updateOld() > i = i + 1 > T = i*(tmax/nt)#min(100, numerix.exp(dexp)) > elapsedt += dt > eq.solve(dt=T) > if __name__ == "__main__": > viewer.plot() > > if __name__ == '__main__': > raw_input("Coupled equations. Press <return> to proceed...") > > [\code] > > I do not have any particular boundary/initial conditions I want to > specifically test at the moment, but besides trivial conditions, I have been > finding the output essentially always diverges. Increasing the number of > steps also appears to freeze the script. So please feel free to test any > conditions you like even if they differ from the ones in my code. Any > thoughts on improving the code and suggestions to solve the above nonlinear, > coupled PDEs would be of much interest. I am also curious if FiPy is > well-suited to handle such a problem involving nonlinear terms in the coupled > PDEs since most examples I have noted are linear and do not typically involve > two independent variables. > > Any and all input is welcome. > > Abhilash > _______________________________________________ > fipy mailing list > fipy@nist.gov > http://www.ctcms.nist.gov/fipy > [ NIST internal ONLY: https://email.nist.gov/mailman/listinfo/fipy ] _______________________________________________ fipy mailing list fipy@nist.gov http://www.ctcms.nist.gov/fipy [ NIST internal ONLY: https://email.nist.gov/mailman/listinfo/fipy ]
_______________________________________________ fipy mailing list fipy@nist.gov http://www.ctcms.nist.gov/fipy [ NIST internal ONLY: https://email.nist.gov/mailman/listinfo/fipy ]