package symjava.examples; import static symjava.math.SymMath.*; import static symjava.symbolic.Symbol.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import Jama.Matrix; import symjava.domains.Domain; import symjava.examples.fem.*; import symjava.math.Transformation; import symjava.matrix.SymMatrix; import symjava.numeric.NumFunc; import symjava.numeric.NumInt; import symjava.relational.Eq; import symjava.symbolic.*; import symjava.symbolic.utils.ExprPair; import symjava.symbolic.utils.Utils; /** * Finite Element solver * */ public class Example7 { public static void main(String[] args) { Mesh2D mesh = new Mesh2D("S_3x3"); mesh.readGridGenMesh("triangle.grd"); Func u = new Func("u", x, y); Func v = new Func("v", x, y); final double eps = 1e-5; Domain neumannBC = mesh.getBoundary(new NumFunc() { { label = "neumannBC"; } @Override public Integer apply(double ...args) { double x = args[0]; //, y = args[1]; if(3.0-x < eps) return 2; // return 0; } }); WeakForm pde = new WeakForm( //Int.apply(1.0*dot(grad(u), grad(v))+sqrt(x*x+y*y)*u*v, mesh) + Int.apply((1.0*u-1.0)*v, neumannBC), //Int.apply(dot(grad(u), grad(v)), mesh) + Int.apply(u*v, neumannBC), //Int.apply(dot(grad(u), grad(v)), mesh), Integrate.apply(u.diff(x)*v.diff(x), mesh) + Integrate.apply(u.diff(y)*v.diff(y), mesh), Integrate.apply((-2*(x*x+y*y)+36)*v, mesh), u, v ); //Mark boundary nodes for(Node n : mesh.nodes) { if(3.0-Math.abs(n.coords[1]) < eps || 3.0+n.coords[0] < eps || 3.0-n.coords[0] < eps) n.setType(1); } Map diri = new HashMap(); diri.put(1, 0.0); //Solve solve(pde, diri, "triangle_neumann.dat"); } public static void solve(WeakForm pde, Map dirichlet, String outputFile) { System.out.println(String.format("Solving: %s == %s", pde.lhs(), pde.rhs())); //Create coordinate transformation Symbol x1 = new Symbol("x1"); Symbol x2 = new Symbol("x2"); Symbol x3 = new Symbol("x3"); Symbol y1 = new Symbol("y1"); Symbol y2 = new Symbol("y2"); Symbol y3 = new Symbol("y3"); Transformation trans = new Transformation( new Eq(x, x1*r+x2*s+x3*(1-r-s), new Expr[]{r, s}), new Eq(y, y1*r+y2*s+y3*(1-r-s), new Expr[]{r, s}) ); //Jacobian matrix of the transformation // jacMat = (xr xs) // (yr ys) SymMatrix jacMat = trans.getJacobianMatrix(); System.out.println(jacMat+"\n"); //Shape functions Func N1 = new Func("R", x, y); Func N2 = new Func("S", x, y); Func N3 = new Func("T", 1 - N1 - N2); Func[] shapeFuns = {N1, N2, N3}; Expr jac = trans.getJacobian(); Expr rx = jacMat[1][1]/jac; //rx = ys/jac Expr ry = -jacMat[0][1]/jac; //ry = -xs/jac //bugfix missed a minus sign! Expr sx = -jacMat[1][0]/jac; //sx = -yr/jac Expr sy = jacMat[0][0]/jac; //sy = xr/jac //Create coordinate transformation for the boundary of a template element //r=[-1,1] Transformation transB = new Transformation( new Eq(x, x1*(1-r)/2.0+x2*(1+r)/2.0), new Eq(y, y1*(1-r)/2.0+y2*(1+r)/2.0) ); //Shape functions on the bounary Func NB1 = new Func("RB"); Func NB2 = new Func("SB", 1 - NB1); Func[] shapeFunsB = {NB1, NB2}; Expr jacB = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))/2.0; //transB.getJacobian(); //Define reference elements RefTriangle refTri = new RefTriangle("RefT", r, s); RefLine refLine = new RefLine("RefL", r); Integrate lhsInt[][] = new Integrate[shapeFuns.length][shapeFuns.length]; Integrate lhsIntB[][] = new Integrate[shapeFunsB.length][shapeFunsB.length]; Integrate rhsInt[] = new Integrate[shapeFuns.length]; Mesh2D mesh = null; Mesh2DBoundary meshB = null; List addList = normalizeTerms(pde.lhs()); //Change of variables for(Expr term : addList) { Integrate intTerm = (Integrate)term; // Integration term //Integrate on the domain if(intTerm.domain instanceof Mesh2D) { if(mesh == null) mesh = (Mesh2D) intTerm.domain; for(int i=0; i subsList = new ArrayList(); //Substitute u, v to shape functions subsList.add(new ExprPair(pde.trial, U)); subsList.add(new ExprPair(pde.test, V)); subsList.add(new ExprPair(N1.diff(x), rx)); subsList.add(new ExprPair(N1.diff(y), ry)); subsList.add(new ExprPair(N2.diff(x), sx)); subsList.add(new ExprPair(N2.diff(y), sy)); subsList.add(new ExprPair(N1, r)); subsList.add(new ExprPair(N2, s)); subsList.add(new ExprPair(x, trans.eqs[0].rhs())); subsList.add(new ExprPair(y, trans.eqs[1].rhs())); lhsInt[i][j] = intTerm.changeOfVars(subsList, jac, refTri); lhsInt[i][j].integrand.setLabel("LHS"+i+j); System.out.println(lhsInt[i][j]+"\n"); } List subsList = new ArrayList(); subsList.add(new ExprPair(pde.test, V)); subsList.add(new ExprPair(N1, r)); subsList.add(new ExprPair(N2, s)); subsList.add(new ExprPair(x, trans.eqs[0].rhs())); subsList.add(new ExprPair(y, trans.eqs[1].rhs())); rhsInt[i] = ((Integrate)pde.rhs()).changeOfVars(subsList, jac, refTri); rhsInt[i].integrand.setLabel("RHS"+i); System.out.println(rhsInt[i]+"\n"); } //Integrate on the boundary of the domain } else if(intTerm.domain instanceof Mesh2DBoundary) { if(meshB == null) meshB = (Mesh2DBoundary) intTerm.domain; for(int i=0; i subsListB = new ArrayList(); //Substitute u, v to shape functions subsListB.add(new ExprPair(pde.trial, U)); subsListB.add(new ExprPair(pde.test, V)); subsListB.add(new ExprPair(NB1, r)); subsListB.add(new ExprPair(NB2, s)); subsListB.add(new ExprPair(x, transB.eqs[0].rhs())); subsListB.add(new ExprPair(y, transB.eqs[1].rhs())); lhsIntB[i][j] = intTerm.changeOfVars(subsListB, jacB, refLine); lhsIntB[i][j].integrand.setLabel("LHSB"+i+j); System.out.println(lhsIntB[i][j]+"\n"); } } } } //Generate bytecode for the integration //You can save the class to some place for later use NumInt lhsNInt[][] = new NumInt[shapeFuns.length][shapeFuns.length]; NumInt lhsNIntB[][] = new NumInt[shapeFunsB.length][shapeFunsB.length]; NumInt rhsNInt[] = new NumInt[shapeFuns.length]; for(int i=0; i normalizeTerms(Expr intTerms) { List addList = new ArrayList(); intTerms.flattenAdd(addList); Map> map = new HashMap>(); for(int i=0; i list = map.get(tmp.domain); if(list == null) { list = new ArrayList(); map.put(tmp.domain, list); } list.add(tmp.integrand); } List rlt = new ArrayList(); for(Entry> entry : map.entrySet()) { rlt.add( Integrate.apply(Utils.addListToExpr(entry.getValue()), entry.getKey()) ); } return rlt; } }