[petsc-users] Conditional Constraints

Shri abhyshr at mcs.anl.gov
Thu Sep 8 21:34:55 CDT 2011


Jon, 


> I do not want Ve to be constant, however; I would like it to either decrease in response to Imag > Imag_max or increase in response to Imag < Imag_max, providing > the condition Vmag <= Vmag_max remains true. 
> Should I then have something like f(Ve_ijk) = Imag - Imag_max? 


Note here that (a) f(Ve_ijk) is a complex function while Imag and Imag_max are real. So the above equation does not hold. 
(b) In your previous email, you had bounds on Imag, 0 < Imag < Imag_max. Now you want Ve_ijk to increase if Imag > Imag_max and decrease if Imag < Imag_max. Are you trying to find the value of Ve at which the current is maximum, i.e. Imag = Imag_max, by doing this? 

----- Original Message -----



Shri, 


Thanks very much for your response. In fact, -snes_converged_reason revealed that the solution was not converging, as you suggested: "Nonlinear solve did not converge due to DIVERGED_LINE_SEARCH." I had not realized this earlier since the voltage distribution in the solution appeared to be correct, even though the SNES_VI constraints were not satisfied. 


Given that and your explanation, I am sure something is wrong with my choices of f. I do not want Ve to be constant, however; I would like it to either decrease in response to Imag > Imag_max or increase in response to Imag < Imag_max, providing the condition Vmag <= Vmag_max remains true. Should I then have something like f(Ve_ijk) = Imag - Imag_max? 





Note that you have 







One more thing from your response: 






>If a block (with coordinates i, j, k) is not occupied by an electrode , C_e is set to zero in the expression for Vb_ijk and all function and Jacobian entries for Ve, >Vmag, and Imag are either not set or set to zero. 






Does this mean f(Ve_ijk) = f(Vmag_ijk) = f(Imag_ijk) = 0? If so, then Ve_ijk, Vmag_ijk, and Imag_ijk would retain their initial values for all time steps. 

In my present scheme, f(Ve_ijk) = f(Vmag_ijk) = 0 and f(Imag_ijk) is non-zero for electrode blocks; all three are zero for non-electrode blocks. Depending on the choice of initial conditions, I can make f(Vmag_ijk) non-zero as well (until Ve changes to match Ve_max). 


Thanks again, 


Jon 


On 2011-09-08, at 3:42 PM, Shri wrote: 




Jon, 


> for Ve_ijk, f = 0.0 + 0.0*i, and all corresponding Jacobian entries are zero as well. Ve_ijk is set to the maximum voltage for each electrode when the initial solution >is - set. Since the magnitude of Ve is constrained rather than Ve itself, I believe this is correct, but could this be why Ve does not change as it should when the >problem is - being solved? 


This f(Ve_ijk) seems very odd to me since normally you would always have f(some/all variables) = 0 as the function. If f=0.0+0.0*i for all steps, then you don't need a seperate variable Ve_ijk, you can treat it as a constant since Ve_ijk will not change its value during the solutions. 


Moroever, the Jacobian rows for df(Ve_ijk)/d(all variables) would be all zeros which implies a singular matrix. I am not sure how the solution converged for this case. Were you using -pc_type lu with some shift or some external direct solver such as superlu? What do you get for -snes_monitor -snes_converged_reason? 




> Ve_ijk is set to the maximum voltage for each electrode when the initial solution is set. Since the magnitude of Ve is constrained rather than Ve itself. 
> for Vmag_ijk, f = abs(Ve_ijk) - abs(Ve_ijk_max) 


Since Ve_ijk = Ve_ijk_max, f for Vmag_ijk = 0.0 and hence Vmag_ijk also will also retain its initial value throughout. 


>If a block (with coordinates i, j, k) is not occupied by an electrode , C_e is set to zero in the expression for Vb_ijk and all function and Jacobian entries for Ve, >Vmag, and Imag are either not set or set to zero. 
Does this mean f(Ve_ijk) = f(Vmag_ijk) = f(Imag_ijk) = 0? If so, then Ve_ijk, Vmag_ijk, and Imag_ijk would retain their initial values for all time steps. 


> When I run my program with -snes_vi_type rs, the solution converges quickly but Vmag voltages remain the same as Ve_max for every electrode. As a result, Imag > currents are far larger than abs(iE_max). 
Seems to me like the problem is not converging, or giving the incorrect solution, since the solution of a variational inequality problem has to satisfy Imag < iE_max, which in your case is not happening. 


Thanks for the detailed explanation. Would you mind if I (or you) forward this to petsc-users list so that others could share their thoughts too. 


Shri 





----- Original Message -----






Hi Shri, 


Thanks again for your patience with my being away this past month. I have spent some more time with this problem and I have added Jacobian entries for 'cross terms' such as d(f(Vb)) / d(Ve). However, this did not appear to change the solution arrived at by PETSc. 


I will give you some examples of the f functions and corresponding Jacobian entries as you suggested, with the hope you will be able to see where I may be going wrong. I will use Vb = V_block, Ve = V_electrode, Vmag = magnitude(V_electrode), Imag = magnitude(I_electrode) to name the four degrees of freedom. 


In my 3D finite differencing grid, there are two types of blocks: blocks occupied by electrodes, and blocks occupied by a resistive medium. The block type of the current block and its neighbouring blocks determines the form of f. This is complicated by the fact that individual electrodes generally occupy three vertically-contiguous blocks, and I want to limit the electric current flowing from the whole electrode rather than the current through each block. Note that Ve, Vmag, and Imag are thus computed or recorded only for the top block of each electrode. 


If a block (with coordinates i, j, k in the x, y, and z directions, respectively) is occupied by an electrode , 
- for Vb_ijk, f = C_posX * Vb_posX + C_posY * Vb_posY + C_posZ * Vb_posZ 
- (C_posX + C_posY + C_posZ + C_negX + C_negY + C_negZ - C_e) * Vb_ijk 
+ C_negX * Vb_negX + C_negY * Vb_negY + C_negZ * Vb_negZ 
- C_e * Ve, 
where all C's are calculated constants that do not depend on the other degrees of freedom, but do depend on the type of the neighbouring block in their assigned directions. Then, 
the Jacobian entries for Vb_ijk are 
df/dVb_negZ = C_negZ (col.i = i, col.j = j, col.k = k - 1) 
df/dVb_negY = C_negY (col.i = i, col.j = j - 1, col.k = k) 
df/dVb_negX = C_negX (col.i = i - 1, col.j = j, col.k = k) 
df/dVb_ijk = - (C_posX + C_posY + C_posZ + C_negX + C_negY + C_negZ - C_e) (col.i = i, col.j = j, col.k = k) 
df/dVb_posX = C_posX (col.i = i + 1, col.j = j, col.k = k) 
df/dVb_posY = C_posY (col.i = i, col.j = j + 1, col.k = k) 
df/dVb_posZ = C_posZ (col.i = i, col.j = j, col.k = k + 1) 
For each of these, row.i = i, row.j = j, row.k = k, and row.c = DOF_VB (the DOF index for Vb). Also, col.c = DOF_VB. 
The only cross term for the Vb_ijk function is 
df/dVe_ijk = -C_e (row.i = i, row.j = j, row.k = k, row.c = DOF_VB, col.i = i, col.j = j, col.k = k col.c = DOF_VE) 


- for Ve_ijk, f = 0.0 + 0.0*i, and all corresponding Jacobian entries are zero as well. Ve_ijk is set to the maximum voltage for each electrode when the initial solution is set. Since the magnitude of Ve is constrained rather than Ve itself, I believe this is correct, but could this be why Ve does not change as it should when the problem is being solved? 


- for Vmag_ijk, f = abs(Ve_ijk) - abs(Ve_ijk_max). The idea was to provide some 'pressure' towards Ve = Ve_max. The corresponding Jacobian entries are 
df/dVmag_ijk = 1.0 + 0.0*i (row.i = i, row.j = j, row.k = k, row.c = DOF_VMAG, col.i = i, col.j = j, col.k = k, col.c = DOF_VMAG) 
df/dVe_ijk = 0.5 * conj(Ve_ijk) / abs(Ve_ijk) (row.i = i, row.j = j, row.k = k, row.c = DOF_VMAG, col.i = i, col.j = j, col.k = k, col.c = DOF_VE) 
(However, since d(abs(Ve_ijk))/dVe_ijk does not have satisfied Cauchy-Reimann equations for the entire complex plane, this derivative does not technically exist.) 


- for Imag_ijk, f = abs(iE) - iE_max. Again, the idea was to provide some 'pressure' towards iE = iE_max. iE is calculated by adding iE_block currents for each block occupied by an electrode. iE_block for block i,j,k is found from 
iE_block_ijk = aE_ijk * (Ve - Vb_ijk) 
where aE_ijk is a constant that does not depend on any degrees of freedom. There is one Ve value per electrode. The Jacobian entries are then 
df/dImag_ijk = 1.0 + 0.0*i (row.i = i, row.j = j, row.k = k, row.c = DOF_IMAG, col.i = i, col.j = j, col.k = k, col.c = DOF_IMAG) 
df/dVe = 0.5 * aE_sum * conj(iE) / abs(iE) (row.i = i, row.j = j, row.k = k, row.c = DOF_IMAG, col.i = i, col.j = j, col.k = k, col.c = DOF_VE) 
df/dVb_ijk = - 0.5 * aE_ijk * conj(iE) / abs(iE) (row.i = i, row.j = j, row.k = k, row.c = DOF_IMAG, col.i = i, col.j = j, col.k = k, col.c = DOF_VB) 
df/dVb_ij(k-1) = - 0.5 * aE_ij(k-1) * conj(iE) / abs(iE) (row.i = i, row.j = j, row.k = k, row.c = DOF_IMAG, col.i = i, col.j = j, col.k = k-1, col.c = DOF_VB) 
df/dVb_ij(k-2) = - 0.5 * aE_ij(k-2) * conj(iE) / abs(iE) (row.i = i, row.j = j, row.k = k, row.c = DOF_IMAG, col.i = i, col.j = j, col.k = k-2, col.c = DOF_VB) 


If a block (with coordinates i, j, k) is not occupied by an electrode , C_e is set to zero in the expression for Vb_ijk and all function and Jacobian entries for Ve, Vmag, and Imag are either not set or set to zero. 


My SNES_VI constraints are set as follows for every block: 
xl_ijk_DOF_V = -SNES_VI_INF 
xu_ijk_DOF_V = SNES_VI_INF 

xl_ijk_DOF_VE = -SNES_VI_INF 
xu_ijk_DOF_VE = SNES_VI_INF 

xl_ijk_DOF_VMAG = 0.0 
xu_ijk_DOF_VMAG = abs(Ve_max) 


xl_ijk_DOF_IMAG = 0.0 
xu_ijk_DOF_IMAG = abs(iE_max) 




When I run my program with -snes_vi_type rs, the solution converges quickly but Vmag voltages remain the same as Ve_max for every electrode. As a result, Imag currents are far larger than abs(iE_max). Are you able to see from here what the problem might be? Again, my hunches are that the complex derivatives do not work in my Jacobian because they do not exist, or that my choices of f for Ve, Vmag, and Imag are not correct. 


Please let me know if you would like clarification on any portion of my description., and thank you again for all your help with this. 


Jon 



On 2011-07-29, at 12:13 PM, Shri wrote: 



Jon, 
I am trying to compile petsc with complex data type right now and will try to test the VI solver with complex variables within the next few hours. 




My understanding is that comparison operators (such as < and >) are 


not defined for complex numbers, so would it be correct to say that 


anyone using complex scalars within PETSc will encounter this problem 


with SNESVI? In other words, SNESVI inequality constraints can only be 


applied to real variables or real-valued functions of complex 


variables? 

For complex scalars, we only compare the real part of the complex variable and bound,i.e., 
real(xl) <= real(x) <= real(x_u). For your application, this real part comparison is sufficient 
since the magnitude is saved in the real part. 








The residuals are set as follows, and the Jacobian entries are set 






correspondingly: 






f[V_block] = {function of adjacent V_blocks, V_electrode} 






f[V_electrode] = 0.0 + 0.0i 






f[magnitude(V_electrode)] = 0.0 + 0.0i 






f[magnitude(I_electrode)] = 0.0 + 0.0i 

Can you give an example of f for all dofs maybe just for one grid point with the following dof names 
Vb - V_block 
Ve - V_electrode 
Vmag - magnitude(V_electrode) 
Imag - magnitude(I_electrode) 



Since I set all the residuals for both magnitude variables to zero, 


and each entry in the Jacobian matrix is a partial derivative of a 


residual, I believe the Jacobian entries for both magnitudes would all 


be zero as well. However, your point made me realize I have no 


Jacobian entry for the partial derivative of f[V_block] w.r.t. 


V_electrode. Is that needed? 

Since f[V_block] is a function of V_electrode, you would need to set the partial derivatives of f[V_block] w.r.t V_electrode 
for correct jacobian evaluation and for having a good newton convergence. 

How would one enter it with 


MatSetValuesStencil? 
ex28.c, 
http://www.mcs.anl.gov/petsc/petsc-as/snapshots/petsc-dev/src/ksp/ksp/examples/tutorials/ex28.c.html , 
is a petsc example which shows how to use MatSetValuesStencil with multiple degrees of freedom. 
See the routine ComputeMatrix in the example. 

My working understanding was that each degree of 


freedom conceptually has its own residual and Jacobian, even though 


all residuals are contained in one Vec and all Jacobians contained in 


one Mat. 




Please bare with us as we are trying to figure out whether the issue is with our VI implementation or something in 
your code is amiss. I appreciate your patience on this matter. 

Btw, one quick question, are all the problem formulations in your field done using complex variables or by decomposing the complex term into real/imaginary or magnitude/angle? My background is in electrical power grid and we mostly use either real/imaginary part or magnitude/angle as the variables. 


Shri 


----- Original Message ----- 


Thanks for your reply, Shri. Responses below: 





On 2011-07-28, at 1:03 PM, Shri wrote: 












----- Original Message ----- 






Hi Barry, Shri, 













I reworked my implementation to include only the time-independent 






electrical problem, and to make use of SNESVISetVariableBounds(). 






However, it does not work quite as I expected: Constraints on 






variables that are functions of other variables have no effect on 






the 






variables by which the functions are defined. 













My constraints are set on the four degrees of freedom as follows: 






-SNES_VI_INF <= V_block <= SNES_VI_INF 






-SNES_VI_INF <= V_electrode <= SNES_VI_INF 






0.0 + 0.0i <= magnitude(V_electrode) <= magnitude(V_electrode_max) 






0.0 + 0.0i <= magnitude(I_electrode) <= magnitude(I_electrode_max) 









Note that while V_block and V_electrode and complex quantities,the 




magnitude terms are actually real numbers. What function did you use 




to compute the magnitude? abs()? sqrt of product of complex number 




with its conjugate? 





I used the "0.0 + 0.0i" there to emphasize that I built PETSc with 


complex scalars, so all the scalars are stored as complex even if the 


imaginary components are always zero. I have been using std::abs() 


from the C++ standard library complex template class 


(std::complex<double>). I believe the values of type 'double' returned 


by std::abs() are implicitly cast to the real part of 


std::complex<double> or PetscScalar, though I usually try to cast 


explicitly. 







This seems like an application where the variables are of type 




complex but the constraints need to be set for functions of the 




variables which are actually real numbers. I am not sure whether 




this can be supported. Maybe Barry or others can shed more 




light on this. 





My understanding is that comparison operators (such as < and >) are 


not defined for complex numbers, so would it be correct to say that 


anyone using complex scalars within PETSc will encounter this problem 


with SNESVI? In other words, SNESVI inequality constraints can only be 


applied to real variables or real-valued functions of complex 


variables? 
















The residuals are set as follows, and the Jacobian entries are set 






correspondingly: 






f[V_block] = {function of adjacent V_blocks, V_electrode} 






f[V_electrode] = 0.0 + 0.0i 






f[magnitude(V_electrode)] = 0.0 + 0.0i 






f[magnitude(I_electrode)] = 0.0 + 0.0i 









What equations do you use for the partial derivatives of the 




magnitude functions w.r.t. the actual complex variables (V_block and 




V_electrode) in the jacobian evaluation? 





Since I set all the residuals for both magnitude variables to zero, 


and each entry in the Jacobian matrix is a partial derivative of a 


residual, I believe the Jacobian entries for both magnitudes would all 


be zero as well. However, your point made me realize I have no 


Jacobian entry for the partial derivative of f[V_block] w.r.t. 


V_electrode. Is that needed? How would one enter it with 


MatSetValuesStencil? My working understanding was that each degree of 


freedom conceptually has its own residual and Jacobian, even though 


all residuals are contained in one Vec and all Jacobians contained in 


one Mat. 
















The first two potentials, V_block and V_electrode, are independent, 






while magnitude(V_electrode) is a function of V_electrode only and 






the 






electrode current magnitude(I_electrode) is a function of V_block 






and 






V_electrode. Note that V_electrode acts as a source term in the 






finite 






difference formulation for V_block. While all of these variables 






are 






complex, the latter two always have zero imaginary parts. I suppose 






I 






am assuming that PETSc knows to compare only the real parts if the 






imaginary parts are zero. (Is this a bad assumption?) 













When solving with PETSc (using -snes_vi_type rs) 









Did you also use -snes_type vi? 





I have been using SNESSetType(snes, SNESVI) in my code, and the use of 


-snes_type vi in the command line does not seem to change any 


behaviour. 












V_electrode stays at 






its maximum, as set in the initial guess, and the V_block 






distribution 






falls properly from that. However, measurements of 






magnitude(I_electrode) are way above maximum and do not move 






downwards 






with successive SNES iterations. I can also set the constraint on 






magnitude(V_electrode) to less than maximum and it does not affect 






the 






value of V_electrode. How can I tell PETSc to change V_electrode 






when 






the magnitude(V_electrode) or magnitude(I_electrode) constraints 






are 






not met? 











Send the code for your application with instructions on how to run 




it and we'll try to figure out what needs to be 




done. 





I really appreciate this generous offer of your time, and I will 


certainly take you up on it if we cannot resolve this otherwise. 


Unfortunately, I will be travelling for the next few weeks and it may 


take me some time to isolate the PETSc-dependent parts of my 


application. Please bear with me as I will try to keep in touch while 


I am away. 





As I mentioned above, I think the issue may lie in the conceptual 


incompatibility of complex variables and inequality constraints, but I 


would appreciate your thoughts on that. 





Thanks again, 





Jon 

















Shri 
















Thanks again for your help. 













Jon 




















On 2011-07-25, at 8:58 PM, Barry Smith wrote: 
























On Jul 25, 2011, at 5:50 PM, Jonathan Backs wrote: 



















Hi Shri, 





















Thanks for your message and all the helpful tips. If the 










TSVISetVariableBounds() functions are available now, I would like 










to try them as well. Is the interface essentially the same as 










with 










SNESVISetVariableBounds()? I will get back to you and Barry when 










I 










have had a chance to modify my application. 





















For my problem, I believe it makes sense to have bounds on one of 










the variables as well as one function of the variables. The two 










relevant degrees of freedom are the block voltage (one for each 










finite difference block) and the electrode voltage (one for each 










electrode, which may be present in multiple blocks). The 










electrode 










voltage should keep a constant phase while the magnitude is 










constrained between zero and some maximum. The block voltages 










near 










the electrodes depend on the electrode voltages as well as the 










neighbouring block voltages. The electrode current for a given 










electrode is a function of its electrode voltage and several 










nearby 










block voltages, and should be constrained in magnitude between 










zero 










and some maximum (and the phase unconstrained). Would I need to 










use 










SNESVISetComputeVariableBounds since the electrode current is a 










function of the other variables? Would any other provisions need 










to 










be made for the block voltages, since they depend on the 










electrode 










voltages? 




























You cannot directly make a bound on some function of other 








variables. Instead you need to introduce another variable that is 








defined to be equal to that function and put the bound on that 








new 








variable. 

















Barry 



















Thank you again, 





















Jon 





















On 2011-07-25, at 11:58 AM, Shri wrote: 




































----- Original Message ----- 














On Jul 22, 2011, at 4:16 PM, Jonathan Backs wrote: 































Barry, 

































Thank you so much for your response. Lucky, indeed! I look 
















forward 
















to trying out these new features. 

































I neglected to mention in my original post that my electrical 
















problem is part of a DAE, which includes a time-dependent 
















heating 
















problem. Can SNESVI constraints be used in conjunction with 
















TSSetIFunction() and TSSetIJacobian() as well? (Of course, I 
















only 
















need the constraints for the time-independent electrical 
















portion.) 





























We have not yet put that in but Shri is starting to look at 














that 














just 














now. Basically we would have a TSVISetVariableBounds() and 














handle 














everything from there. I suggest you start with a simple time 














electrical portion with constraints to explore and we'll go 














from 














there. Shri is actually a electrical networks guy and so can 














speak 














your language. 






































I've added TSVISetVariableBounds() for setting the bounds on the 












variables using the TS object directly. 












A few things that i want to mention here about using the 












variational inequality nonlinear solver (SNESVI). 












i) Use the runtime option -snes_type vi or explicitly set 












SNESSetType(snes,SNESVI). 












ii) There are two tested algorithms currently available, (a) 












semismooth (-snes_vi_type ss) and (b) active set or reduced 












space 












(-snes_vi_type rs). 












iii) Take a look at example,ex61.c, in 












src/snes/examples/tutorials 












which is a time-stepping nonlinear problem with constraints on 












the 












variables. This example does not use the TS object directly but 












rather a time-loop is explicitly written. Another example,ex8.c, 












in src/snes/examples/tests/ is a minimum surface area problem 












which uses SNESVI. 

























By the way, does your problem have bounds on the variables or 












bounds on some function of the variables? 

























Shri 




































































Barry 














































































Thank you again, 

































Jon 

































On 2011-07-22, at 2:46 PM, Barry Smith wrote: 






















































Jon, 





































You may be in luck. In PETSc-dev 


















http://www.mcs.anl.gov/petsc/petsc-as/developers/index.html 


















we 


















have now implemented variational inequality non-linear 


















solvers 


















with box constraints. 





































That is one has a set of variables u and algebraic equations 


















F(u) = 0 (say of size n each) but in addition one has 


















constraints lu <= u <= uu where some or all of lu may be 


















negative infinity (no constraints) and some or all of uu may 


















be 


















infinity (no constraints). There is also a constraint on the 


















sign of F() for those equations associated with active 


















constraints. If your constraints are not in this form 


















sometimes 


















you can introduce new additional variables to get it in this 


















form. Read up a little on variational inequalities on the 


















web. 





































To use this you provide the usual SNES function and Jacobian 


















but 


















you also provide SNESVISetVariableBounds() there is a manual 


















page for this function and for for SNESVI at 


















http://www.mcs.anl.gov/petsc/petsc-as/snapshots/petsc-dev/docs/index.html 


















(the link is broken right now but Satish is fixing it). Plus 


















several examples in src/snes/examples/tutorials (in 


















petsc-dev). 





































This is all new code so we would be interested in your 


















feedback. 
























































Barry 

















































































































On Jul 22, 2011, at 3:33 PM, Jonathan Backs wrote: 







































Hi, 









































I am trying to add a constraint feature to my first PETSc 




















application, which uses the finite difference method to 




















calculate 




















the potential distribution produced by a collection of 




















electrodes 




















in a resistive medium. I would like to make this simulation 




















more 




















realistic by imposing a maximum electric current and a 




















maximum 




















potential difference that can be supplied to each electrode 




















by 




















the 




















power supply. If the medium between the electrodes is very 




















conductive, the current maximum would be exceeded by the 




















maximum 




















potential difference, so the potential difference should be 




















decreased from maximum until it produces the maximum 




















current. 




















On 




















the other hand, the potential difference between the 




















electrodes 




















should remain at maximum as long as the current remains 




















below 




















maximum (say, for a less conductive medium). 









































I added an extra degree of freedom (the electrode voltages) 




















to 




















my 




















DMDA, and I developed a set of conditional expressions that 




















describe the above constraints, but one problem is that the 




















logic 




















relies on if-then-else decisions that are made when forming 




















the 




















function/residual and the Jacobian. Once these decisions are 




















made, 




















of course, the conditions are not checked again until the 




















next 




















function or Jacobian evaluation. The non-linear solver then 




















tends 




















to oscillate between extreme solutions to the opposing 




















conditions 




















with each iteration, and never converges towards a 




















reasonable 




















solution. 









































Is there a better strategy for solving such problems? Does 




















PETSc 




















offer mechanisms to aid in their solution? I would very much 




















appreciate any hints. 









































Thank you for your time, 









































Jon 
















































































-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/petsc-users/attachments/20110908/0af5c3db/attachment-0001.htm>


More information about the petsc-users mailing list