program main use FEMDomainClass use DiffusionEquationClass use SceneClass use FactoryClass implicit none type(DiffusionEq_) :: solver type(FEMDomain_) :: cube(4) real(real64),allocatable :: c(:) real(real64),allocatable :: DiffusionCoeff(:) real(real64),allocatable :: Reaction(:) real(real64),allocatable :: FixValue(:) real(real64),allocatable :: C_n(:),x(:) integer(int32),allocatable :: FixBoundary(:) integer(int32) :: itr,offset,max_itr real(real64) :: Length,epsi,dt,penalty,d,AL_lambda, AL_tol, AL_alpha,bc_val type(IO_) :: f logical :: passed type(Scene_) :: scene type(Factory_) :: factory type(COO_) :: coo type(CRS_) :: crs bc_val = -1.0d0 ! diffusion_benchmark_EbO_Scene.f90 Length=1.00d0 epsi=0.010d0 max_itr = 1000 dt = 0.030d0 !dt = 0.0010d0 ! for Forward-Euler !penalty = 10.0d0**(-4) ! for Forward-Euler penalty = 10.0d0**(2) d = 1.0e-2 AL_lambda= 0.00d0 AL_tol = dble(5.0e-9) AL_alpha = 3.00d0 ! penaltyを上げるとgapが閉じずに発散する cube = factory%cube([30,5,5],n=4) call scene%add(cube) call scene%resize(object=[1,2,3,4], & x=(Length+3*epsi)/4.0d0 ,y=Length/10.0d0,z=Length/10.0d0) call scene%move(object=[1], x=0.0d0) call scene%move(object=[2], x=cube(1)%xmax()-epsi) call scene%move(object=[3], x=cube(2)%xmax()-epsi) call scene%move(object=[4], x=cube(3)%xmax()-epsi) call scene%vtk("cube") call scene%overset() FixBoundary = scene%select_point_ID([1],x_max=scene%xmin([1]) ) & // scene%select_point_ID([4],x_min=scene%xmax([4]) ) FixValue = scene%full([1],values=bc_val,x_max=scene%xmin([1]) ) & // scene%full([4],values=bc_val,x_min=scene%xmax([4]) ) DiffusionCoeff = d*eyes(scene%nn() ) C_n = scene%full(func=sin_function) call scene%vtk("init",scalar=C_n) call f%open("init.csv","w") x = scene%x() do i_i=1,size(scene%x()) write(f%fh,*) x(i_i), sin_function(x=[x(i_i)]) enddo call f%close() call f%open("analytical.csv","w") x = scene%x() do i_i=1,size(scene%x()) write(f%fh,*) x(i_i), analytical_solution( & x=[x(i_i), 0.0d0], & params=[DiffusionCoeff(1)] ) enddo call f%close() c = c_n call solver%check_stability_condition(dt=dt,dx=Length/80,coefficient=dble(1.0e-4),passed=passed) if(.not.passed)stop do itr=1,max_itr Reaction = zeros( scene%nn() ) solver%solver%debug=True solver%solver%itrmax=100000 ! AL ! c = solver%getDiffusionField(& ! FEMDomains=cube, & ! DiffusionCoeff=DiffusionCoeff, & ! Reaction=Reaction, & ! Penalty=penalty ,& ! FixBoundary=FixBoundary, & ! FixValue=FixValue , & ! C_n=C_n,& ! AL_lambda=AL_lambda,& ! AL_tol=AL_tol,& ! AL_alpha=AL_alpha,& ! dt=dt & ! ) c = solver%getDiffusionField(& FEMDomains=cube, & DiffusionCoeff=DiffusionCoeff, & Reaction=Reaction, & Penalty=penalty ,& FixBoundary=FixBoundary, & FixValue=FixValue , & C_n=C_n,& dt=dt & ) C_n = c call f%open("result.csv","w") call f%write(scene%x(),c(:) ) call f%close() call f%cp("result.csv","result"+str(penalty)+zfill(itr,4)+".csv") call f%open("analytical.csv","w") x = scene%x() do i_i=1,size(scene%x()) call f%write(x(i_i), analytical_solution( & x=[x(i_i), dt*itr], & params=[DiffusionCoeff(1)] ) ) enddo call f%close() enddo contains function sin_function(x,params) result(ret) real(real64),intent(in) :: x(:) real(real64),optional,intent(in) :: params(:) real(real64) :: ret type(Math_) :: math ret = sin(math%pi*x(1))+bc_val end function function analytical_solution(x,params) result(ret) real(real64),intent(in) :: x(:) real(real64),optional,intent(in) :: params(:) real(real64) :: ret type(Math_) :: math ! x1 = x ! x2 = t ret = sin(math%PI*x(1) )& *exp(-params(1)*math%PI*math%PI*x(2) )+bc_val end function end program