-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathVFFlow_SNESMixedFEM.c
147 lines (136 loc) · 5.63 KB
/
VFFlow_SNESMixedFEM.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
VFFlow_MixedFEM.c
A mixed finite elements Darcy solver based on the method in
Masud, A. and Hughes, T. J. (2002). A stabilized mixed finite element method for
Darcy flow. Computer Methods in Applied Mechanics and Engineering, 191(3940):43414370.
(c) 2011-2012 C. Chukwudozie, LSU
*/
#include "petsc.h"
#include "VFCartFE.h"
#include "VFCommon.h"
#include "VFFlow.h"
#include "VFFlow_SNESMixedFEM.h"
#include "VFFlow_KSPMixedFEM.h"
#include "VFWell.h"
/*
VFFlow_DarcyMixedFEMSNES
*/
/*
################################################################################################################
SNES ROUTINE
################################################################################################################
*/
#undef __FUNCT__
#define __FUNCT__ "MixedFEMSNESFlowSolverInitialize"
extern PetscErrorCode MixedFEMSNESFlowSolverInitialize(VFCtx *ctx, VFFields *fields)
{
PetscErrorCode ierr;
PetscFunctionBegin;
ierr = SNESCreate(PETSC_COMM_WORLD,&ctx->snesVelP);CHKERRQ(ierr);
ierr = SNESAppendOptionsPrefix(ctx->snesVelP,"FlowSnes_");CHKERRQ(ierr);
ierr = SNESSetFromOptions(ctx->snesVelP);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "MixedFEMSNESFlowSolverFinalize"
extern PetscErrorCode MixedFEMSNESFlowSolverFinalize(VFCtx *ctx,VFFields *fields)
{
PetscErrorCode ierr;
PetscFunctionBegin;
ierr = SNESDestroy(&ctx->snesVelP);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "FormSNESIFunction"
extern PetscErrorCode FormSNESIFunction(SNES snes,Vec VelnPress,Vec Func,void *user)
{
PetscErrorCode ierr;
VFCtx *ctx=(VFCtx*)user;
Vec VecRHS;
PetscReal theta;
PetscReal one_minus_theta;
PetscFunctionBegin;
ierr = VecSet(Func,0.0);CHKERRQ(ierr);
theta = ctx->theta;
one_minus_theta = (1.-theta);
ierr = VecDuplicate(ctx->RHSVelP,&VecRHS);CHKERRQ(ierr);
ierr = VecCopy(ctx->RHSVelP,VecRHS);CHKERRQ(ierr);
ierr = VecAXPBY(VecRHS,one_minus_theta,theta,ctx->RHSVelPpre);CHKERRQ(ierr);
ierr = MatMultAdd(ctx->KVelPlhs,ctx->PreFlowFields,VecRHS,VecRHS);CHKERRQ(ierr);
ierr = VecApplyVelocityBC(VecRHS,ctx->VelBCArray,&ctx->bcQ[0],ctx);CHKERRQ(ierr);
ierr = MatMult(ctx->KVelP,VelnPress,Func);CHKERRQ(ierr);
ierr = VecAXPY(Func,-1.0,VecRHS);CHKERRQ(ierr);
ierr = VecDestroy(&VecRHS);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "MixedFlowFEMSNESSolve"
extern PetscErrorCode MixedFlowFEMSNESSolve(VFCtx *ctx,VFFields *fields)
{
PetscErrorCode ierr;
SNESConvergedReason reason;
PetscReal ****VelnPress_array;
PetscReal ***Press_array;
PetscReal ****vel_array;
PetscInt i,j,k,c,veldof = 3;
PetscInt xs,xm,ys,ym,zs,zm;
PetscInt its;
PetscReal Velmin,Velmax;
PetscReal Pmin,Pmax;
PetscFunctionBegin;
ierr = FlowMatnVecAssemble(ctx->KVelP,ctx->KVelPlhs,ctx->RHSVelP,fields,ctx);CHKERRQ(ierr);
ierr = SNESSetFunction(ctx->snesVelP,ctx->FlowFunct,FormSNESIFunction,ctx);CHKERRQ(ierr);
ierr = SNESSetJacobian(ctx->snesVelP,ctx->JacVelP,ctx->JacVelP,FormSNESIJacobian,ctx);CHKERRQ(ierr);
if (ctx->verbose > 1) {
ierr = SNESMonitorSet(ctx->snesVelP,FEMSNESMonitor,NULL,NULL);CHKERRQ(ierr);
}
ierr = SNESSolve(ctx->snesVelP,NULL,fields->VelnPress);CHKERRQ(ierr);
ierr = SNESGetConvergedReason(ctx->snesVelP,&reason);CHKERRQ(ierr);
if (reason < 0) {
ierr = PetscPrintf(PETSC_COMM_WORLD,"[ERROR] snes_MixedFlowSolver diverged with reason %d\n",(int)reason);CHKERRQ(ierr);
} else {
ierr = SNESGetIterationNumber(ctx->snesVelP,&its);CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD," snes_MixedFlowSolver converged in %d iterations %d.\n",(int)its,(int)reason);CHKERRQ(ierr);
}
ierr = DMDAGetCorners(ctx->daScal,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr);
ierr = DMDAVecGetArray(ctx->daScal,fields->pressure,&Press_array);CHKERRQ(ierr);
ierr = DMDAVecGetArrayDOF(ctx->daVect,fields->velocity,&vel_array);CHKERRQ(ierr);
ierr = DMDAVecGetArrayDOF(ctx->daFlow,fields->VelnPress,&VelnPress_array);CHKERRQ(ierr);
for (k = zs; k < zs+zm; k++) {
for (j = ys; j < ys+ym; j++) {
for (i = xs; i < xs+xm; i++) {
Press_array[k][j][i] = VelnPress_array[k][j][i][3];
for (c = 0; c < veldof; c++) {
vel_array[k][j][i][c] = VelnPress_array[k][j][i][c];
}
}
}
}
ierr = DMDAVecRestoreArray(ctx->daScal,fields->pressure,&Press_array);CHKERRQ(ierr);
ierr = DMDAVecRestoreArrayDOF(ctx->daVect,fields->velocity,&vel_array);CHKERRQ(ierr);
ierr = DMDAVecRestoreArrayDOF(ctx->daFlow,fields->VelnPress,&VelnPress_array);CHKERRQ(ierr);
ierr = VecMin(fields->velocity,NULL,&Velmin);CHKERRQ(ierr);
ierr = VecMax(fields->velocity,NULL,&Velmax);CHKERRQ(ierr);
ierr = VecMin(fields->pressure,NULL,&Pmin);CHKERRQ(ierr);
ierr = VecMax(fields->pressure,NULL,&Pmax);CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD," Velocity min / max: %e %e\n",Velmin,Velmax);CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD," Pressure min / max: %e %e\n",Pmin,Pmax);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "FormSNESIJacobian"
extern PetscErrorCode FormSNESIJacobian(SNES snes,Vec VelnPress,Mat Jac,Mat Jacpre,void *user)
{
PetscErrorCode ierr;
VFCtx *ctx=(VFCtx*)user;
PetscFunctionBegin;
ierr = MatCopy(ctx->KVelP,Jacpre,DIFFERENT_NONZERO_PATTERN);
ierr = MatAssemblyBegin(Jacpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
ierr = MatAssemblyEnd(Jacpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
if (Jac != Jacpre) {
ierr = MatCopy(Jacpre,Jac,DIFFERENT_NONZERO_PATTERN);
ierr = MatAssemblyBegin(Jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
ierr = MatAssemblyEnd(Jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
}
PetscFunctionReturn(0);
}